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?

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top