Accessing `self` from nested function in the field of R6 class

57 Views Asked by At

I have a reproducible example below. In this example, I try to access the field name from the method method() via self$:

library(R6)

Person <- R6Class("Person",
    public = list(
        name = NULL,
        level1 = list(
            level2 = list(
                level3 = list(
                    method = function() {
                        print(self$name)
                    }
                )
            )
        ),
        initialize = function(name) {
            self$name = name
        }
    )
)

jay = Person$new(name = "Jay")
jay$level1$level2$level3$method()

I have several nested fields, and at some point, I have a function that accesses the public field via self$. However, it throws an error Error in print(self$name) : object 'self' not found. I found a similar issue here, however, the workaround relies on updating R6. Is there any other workaround?

1

There are 1 best solutions below

1
On

In R6, methods are manipulated so that their environments can see self. This is done when an instance of the class is created: the code in new() modifies the environments of the methods. However, in your example, method() is created and called as an element of a list, not as a function declared within public, so new() doesn't see it as a method.

To fix this, you should declare method() at the top level, either public or private, and get it from there during initialization. For example,

library(R6)

Person <- R6Class("Person",
                  public = list(
                    name = NULL,
                    
                    level1 = list(
                      level2 = list(
                        level3 = list()
                      )
                    ),
                    
                    initialize = function(name) {
                      self$name = name
                      self$level1$level2$level3$method <- 
                        private$themethod
                    }
                  ),
                  
                private = list(
                  themethod = function() {
                    print(self$name)
                  }
                )
)

jay = Person$new(name = "Jay")
jay$level1$level2$level3$method()
#> [1] "Jay"

Created on 2023-11-14 with reprex v2.0.2