当前位置 : 主页 > 网络推广 > seo >

在检索S4参考类的字段值时,避免考虑封闭帧

来源:互联网 收集:自由互联 发布时间:2021-06-16
我是S4参考类的忠实粉丝,因为它们允许混合编程风格(功能/按值传递与oop / pass-by-reference; example),从而显着提高灵活性. 但是,当你要求它通过方法$field()检索某个字段值时,我认为我只是遇
我是S4参考类的忠实粉丝,因为它们允许混合编程风格(功能/按值传递与oop / pass-by-reference; example),从而显着提高灵活性.

但是,当你要求它通过方法$field()检索某个字段值时,我认为我只是遇到了一个关于R扫描环境/帧的方式的不良行为(见help page).问题是如果在实际的本地/目标环境中找不到所需的字段(这将是构成S4参考类的环境),R似乎也会查看封闭的环境/帧,即它就像运行get(&lt ; 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字段名称,则可能是错误?

网友评论