0

当我为类本身赋予类生成器不同的名称时(这样做是有正当理由的),我开始遇到问题:

myClassGen <- setRefClass("myClass",
    methods = list(foo = function() baz())
)
myClassGen$methods(baz = function() "baz")

myObj <- myClassGen()
myObj$foo()

导致:

Error in myObj$foo() : could not find function "baz"

然而方法baz显然存在,因为我可以这样做:

> myObj$baz
Class method definition for method baz()
function () 
"baz"
<environment: 0x000000002c60f0b8>

如果将生成器名称更改为 ,则不会出现上述错误myClass

如果这种行为是设计使然,为什么?如果这是一个错误,那么我该如何解决这个问题?生成器和类的名称不同会导致其他隐藏问题吗?

4

1 回答 1

3

您需要指定baz()必须在类实例上调用,依此类推.self

myClassGen <- setRefClass("myClass",methods = list(foo = function() .self$baz()))
myClassGen$methods(baz = function() "baz")

myObj <- myClassGen()
myObj$foo()
# [1] "baz"

因此,问题与类生成器的名称与类名不同无关,因为以下代码不起作用(注意缺少.self):

myClass <- setRefClass("myClass", methods = list(foo = function() baz()))
myClass$methods(baz = function() "baz")

myObj <- myClass()
myObj$foo()
# Error in myObj$foo() : could not find function "baz"

参考类的官方文档在这里


编辑(根据评论):

有关$methods(...)功能的部分中的文档说明:

新方法可以通过名称引用任何当前定义的方法(包括在此调用 $methods() 中提供的其他方法。请注意,虽然以前定义的方法没有重新分析,这意味着它们不会调用新方法(除非它重新定义同名的现有方法)。

如果我理解正确,这意味着新添加的方法baz不能被之前定义的方法调用foo。如果是这样,为什么.self$foo()工作正常?
我不确定,但我想这与对上文提到的方法的分析有关。
可能setRefClass会解析通过定义的方法,如果找到对另一个类方法的调用,该调用会以某种方式显式链接到该类方法以避免与可能存在的具有相同名称的函数混淆(作为过度简化,我想这些调用以.self$) 为前缀。
相反,方法调用.self$something()不会被修改,因为它们已经是显式的。

以下测试似乎合理地支持了这一点。例如,如果我们运行以下代码:

myClassGen <- setRefClass("myClass", methods = list(foo = function() baz(), 
                                                    baz = function() "baz"))
myObj <- myClassGen()
myObj$foo

我们得到:

Class method definition for method foo()
function () 
baz()
<environment: 0x000000000e490938>

 Methods used:  
    "baz"

您可以注意到最后一行说明该方法baz使用了类foo方法。

如果我们改为运行它:

myClassGen <- setRefClass("myClass",methods = list(foo = function() .self$baz(), 
                                                   baz = function() "baz"))
myObj <- myClassGen()
myObj$foo

我们得到:

Class method definition for method foo()
function () 
.self$baz()
<environment: 0x00000000107ab5c8>

没有提到类方法的地方baz

于 2014-01-17T08:31:01.750 回答