Search code examples
roopreference-class

The equivalent of 'this' or 'self' in R


I am looking for the equivalent of python's 'self' keyword or java's 'this' keyword in R. In the following example I am making an S4 object from a method of a different S4 object and need to pass a pointer to myself. Is there something in the language to help me do this?

MyPrinter <- setRefClass("MyPrinter",
  fields = list(obj= "MyObject"),
  methods = list(
    prettyPrint = function() {
      print(obj$age)
      # do more stuff
    }
  )
)

MyObject <- setRefClass("MyObject",
  fields = list(name = "character", age = "numeric"),
  methods = list(
    getPrinter = function() {
      MyPrinter$new(obj=WHAT_GOES_HERE) #<--- THIS LINE
    }
  )
)

I can do this with a freestanding method but I was hoping for a nice object-oriented way of doing this operation in R. Thanks


Solution

  • Reference class (RC) objects are basically S4 objects that wrap an environment. The environment holds the fields of the RC object, and is set as the enclosing environment of its methods; that's how unqualified references to the field identifiers bind to the instance's fields. I was able to find a .self object sitting in the environment that I believe is exactly what you're looking for.

    x <- MyObject$new(); ## make a new RC object from the generator
    x; ## how the RC object prints itself
    ## Reference class object of class "MyObject"
    ## Field "name":
    ## character(0)
    ## Field "age":
    ## numeric(0)
    is(x,'refClass'); ## it's an RC object
    ## [1] TRUE
    isS4(x); ## it's also an S4 object; the RC OOP system is built on top of S4
    ## [1] TRUE
    slotNames(x); ## only one S4 slot
    ## [1] ".xData"
    x@.xData; ## it's an environment
    ## <environment: 0x602c0e3b0>
    environment(x$getPrinter); ## the RC object environment is set as the closure of its methods
    ## <environment: 0x602c0e3b0>
    ls(x@.xData,all.names=T); ## list its names; require all.names=T to get dot-prefixed names
    ## [1] ".->age"       ".->name"      ".refClassDef" ".self"        "age"          "field"
    ## [7] "getClass"     "name"         "show"
    x@.xData$.self; ## .self pseudo-field points back to the self object
    ## Reference class object of class "MyObject"
    ## Field "name":
    ## character(0)
    ## Field "age":
    ## numeric(0)
    

    So the solution is:

    MyObject <- setRefClass("MyObject",
        fields = list(name = "character", age = "numeric"),
        methods = list(
            getPrinter = function() {
                MyPrinter$new(obj=.self)
            }
        )
    )