Question

When I gave class generators different names to the class itself (there are legitimate reasons for doing this), I started running into problems:

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

myObj <- myClassGen()
myObj$foo()

resulted in:

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

yet method baz clearly exists because I can do:

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

The above error does not occur if the generator name is changed to myClass.

If this behavior is by design, why? If this is a bug, then how can I fix this issue? Are there another hidden problems resulting from generators and classes having different names?

Était-ce utile?

La solution

You need to specify that baz() has to be called on the class instance, so on .self :

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

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

So, the problem is not related to the name of the class generator being different from the class name, because the following code doesn't work (note the missing .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"

Official documentation on Reference Classes is here.


EDIT (as per comment):

The documentation in the section regarding $methods(...) function states:

The new methods can refer to any currently defined method by name (including other methods supplied in this call to $methods(). Note though that previously defined methods are not re-analyzed meaning that they will not call the new method (unless it redefines an existing method of the same name).

If I understand correctly, this means that the new added method baz cannot be called by the previously defined method foo. If so, why does .self$foo() work fine ?
I'm not sure but I guess it has to do with the analysis of the methods mentioned in the text above.
Probably the methods defined through setRefClass are parsed and, if a call to another class method is found, the call is somehow explicitly linked to that class method to avoid confusion with a possibly existing function having the same name (as an oversimplification I imagine that these calls are prefixed by with .self$).
Instead, method calls to .self$something() are not modified since they are already explicit.

This seems reasonably supported by the following tests. For example if we run this code:

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

we get:

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

 Methods used:  
    "baz"

where you can notice the last line stating that the class method baz is used by the foo method.

If we run this instead:

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

we get:

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

where there's no mention of the class method baz.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top