4

Is there a way to list only those methods of a Reference Class, that were explicitly defined in the class definition (as opposed to those methods inherited by "system classes" such as refObjectGenerator or envRefClass)?

Example <- setRefClass(
    Class="Example",
    fields=list(
    ),
    methods=list(
        testMethodA=function() {
            "Test method A"
        },
        testMethodB=function() {
            "Test method B"
        }
    )
)

What you currently get by calling the $methods() method (see ?setRefClass):

> Example$methods()
 [1] "callSuper"    "copy"         "export"       "field"        "getClass"    
 [6] "getRefClass"  "import"       "initFields"   "show"         "testMethodA" 
[11] "testMethodB"  "trace"        "untrace"      "usingMethods"

What I'm looking for:

> Example$methods()
 [1] "testMethodA" "testMethodB"
Rappster
  • 12,762
  • 7
  • 71
  • 120

2 Answers2

3

1) Try this:

> Dummy <- setRefClass(Class = "dummy")
> setdiff(Example$methods(), Dummy$methods())
[1] "testMethodA" "testMethodB"

2) Here is a second approach which seems to work here but you might want to test it out more:

names(Filter(function(x) attr(x, "refClassName") == Example$className, 
    as.list(Example$def@refMethods)))
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • Thanks, that's my current workaround as well. But I wondered if there's something more build-in as I don't like the idea of having a dummy class just for the sake of an explicit comparison. – Rappster Feb 18 '14 at 00:46
  • I have added a second approach. – G. Grothendieck Feb 18 '14 at 01:21
  • Wow, some awesome `Filter` kung fu there! :-) Never used that function before, but seems very powerful! Thanks man. – Rappster Feb 18 '14 at 01:31
  • I just don't completely get `Filter` yet: what's `f` actually applied to, i.e. what's the `x` when calling `f` inside of `Filter`? The result will give me a position index that's used to index the second arg of `Filter`, i.e. the vector of method names, right? Is there a way to see the result of executing `f` seperately? – Rappster Feb 18 '14 at 01:47
  • `Filter` applies the function to each component of the list and then returns those components for which the function result was `TRUE`. – G. Grothendieck Feb 18 '14 at 01:52
  • Ah, okay got it! I was looking for those `refClassName` attributes in `attributes(getClass("Example"))` etc. and couldn't find it. But actually pretty obvious that it must be somewhere in `x` of `Filter` (`names(attributes(as.list(Example$def@refMethods)[[1]]))`) ;-) Thanks again. – Rappster Feb 18 '14 at 02:00
2

No, because the methods in a reference class "inherited" from the parent are actually copied into the class when it is generated.

setRefClass("Example", methods = list(
  a = function() {}, 
  b = function() {}
))

class <- getClass("Example")
ls(class@refMethods)
#> [1]  "a"            "b"            "callSuper"    "copy"         "export"      
#> [6]  "field"        "getClass"     "getRefClass"  "import"       "initFields"  
#> [11] "show"         "trace"        "untrace"      "usingMethods"

But you can find out the method also defined in the parent and return those:

parent <- getClass(class@refSuperClasses)
ls(parent@refMethods)
#> [1]  "callSuper"    "copy"         "export"       "field"        "getClass"    
#> [6]  "getRefClass"  "import"       "initFields"   "show"         "trace"       
#> [11] "untrace"      "usingMethods"

(note that I'm ignoring the possibility that your class has multiple parents, but that would be easy to generalise)

And then use setdiff() to find the difference

setdiff(ls(class@refMethods), ls(parent@refMethods))
#> [1] "a" "b"
hadley
  • 102,019
  • 32
  • 183
  • 245
  • Thanks for clarifying that. Read your answer prior to Gabor's update and thus thought his answer should "fail" as `Example$def@refMethods` looks a lot like `class@refMethods`. But seems like filtering the actual attribute entries for the respectiv class name (`Filter()`) does the trick! – Rappster Feb 18 '14 at 01:37