但是,当你要求它通过方法$field()检索某个字段值时,我认为我只是遇到了一个关于R扫描环境/帧的方式的不良行为(见help page).问题是如果在实际的本地/目标环境中找不到所需的字段(这将是构成S4参考类的环境),R似乎也会查看封闭的环境/帧,即它就像运行get(< ; objname>,inherits = TRUE)(见help page).
实际问题
为了让R只是在本地/目标环境中查看,我想的是像$field(name =“< fieldname>”,inherits = FALSE),但是$field()没有…参数将允许我将inherits = FALSE传递给get()(我猜这是沿途的某个地方).这有解决方法吗?
代码示例
对于那些对更多细节感兴趣的人:这是一个说明行为的小代码示例
setRefClass("A", fields=list(a="character")) x <- getRefClass("A")$new(a="a")
A类中有一个字段a,因此它在目标环境中找到并返回值:
> x$field("a") [1] "a"
如果我们尝试访问不是引用类的字段但恰好具有与工作空间/搜索路径中的某个其他对象(在本例中为“lm”)的名称相同的字段,则情况会有所不同:
require("MASS") > x$field("lm") function (formula, data, subset, weights, na.action, method = "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL, offset, ...) { ret.x <- x ret.y <- y [omitted] if (!qr) z$qr <- NULL z } <bytecode: 0x02e6b654> <environment: namespace:stats>
这不是我期望的.恕我直言错误或至少一个警告会好得多.或者打开方法$field()为参数,可以传递给其他函数….我猜测在调用$field()时调用get()的方式,所以这样的事情可能会阻止上面的发生的行为:
x$field("digest", inherits=FALSE)
解决方法:自己的提案
这应该可以解决问题,但也许有一些更优雅的东西不涉及在$field()之上指定新方法:
setRefClass("A", fields=list(a="character"), methods=list( myField=function(name, ...) { # VALIDATE NAME // if (!name %in% names(getRefClass(class(.self))$fields())) { stop(paste0("Invalid field name: '", name, "'")) } # // .self$field(name=name) } ) ) x <- getRefClass("A")$new(a="a") > x$myField("a") [1] "a" > x$myField("lm") Error in x$myField("lm") : Invalid field name: 'lm'默认的field()方法可以替换为您自己的.因此,添加一个继承参数以避免封闭框架只是抓住现有的x $字段定义并添加它…
setRefClass( Class="B", fields= list( a="character" ), methods= list( field = function(name, value, inherits=TRUE ) { if( missing(value) ) { get( name, envir=.self, inherits=inherits ) } else { if( is.na( match( name, names( .refClassDef@fieldClasses ) ) ) ) { stop(gettextf("%s is not a field in this class", sQuote(name)), domain = NA) } assign(name, value, envir = .self) } } ), )
或者您可以通过一些重新排列获得一个很好的错误消息
setRefClass( Class="C", fields= list( a="character" ), methods= list( field = function(name, value, inherits=TRUE ) { if( is.na( match( name, names( .refClassDef@fieldClasses ) ) ) && ( !missing(value) || inherits==FALSE) ) { stop(gettextf("%s is not a field in this class", sQuote(name)), domain = NA) } if( missing(value) ) { get( name, envir=.self, inherits=inherits ) } else { assign(name, value, envir = .self) } } ), )
由于您可以定义任何自己的方法来替换默认值,因此几乎可以为您的refclasses实现所需的任何逻辑.如果使用继承获取变量但模式匹配c(“expression”,“name”,“symbol”,“function”),并且如果它不直接匹配本地refClass字段名称,则可能是错误?