5

I was curious if there was a way to create class variables for R6 classes within the definition of the class? I read through the Introduction to R6 classes vignette but didn't find any mention of class variables. I am able to create class variables after creating the class using ClassName$variableName <- initial_value but was curious if there was a way to do this within the actual class definition.

As an example, consider the Person class below, which has a class variable count which keeps track of the number of Person objects that have been instantiated:

library(R6)

Person <- R6Class("Person",
  public = list(
    name = NA,

    initialize = function(name) {
      Person$count <- Person$count + 1
      if (!missing(name)) self$name <- name
    }
  )
)

Person$count <- 0

Person$count # 0
john <- Person$new("John")
Person$count # 1
james <- Person$new("James")
Person$count # 2
jeromefroe
  • 1,345
  • 12
  • 19

1 Answers1

5

Not exactly what you were asking for, but this might help. You can add an environment to the class to store variables that are shared among all instances of a class. Because of the reference semantics of environments, this environment does not get reset whenever a new Person instance is created.

Here is an Example

library(R6)

Person = R6Class(
  "Person",
  public = list(
    name = NA,
    initialize = function( name ){
      if (!missing(name)) self$name <- name
      counter = self$getCounter()
      private$shared_env$counter = counter + 1
    },
    getCounter = function(){
      counter = private$shared_env$counter
      if( is.null( counter ) )
        counter =  0
      return( counter )
    }
  ),
  private = list(
    shared_env = new.env()
  )
)

Testing the code

john <- Person$new("John")
john$getCounter()
# 1
james <- Person$new("James")
james$getCounter()
# 2
john$getCounter()
# 2

You can combine this method with active bindings to make things like john$counter, etc work as well. If you want to decrease the counter when the object is destroyed, use the finalize method in R6.

Gregor de Cillia
  • 7,397
  • 1
  • 26
  • 43
  • It looks like the following document https://r6.r-lib.org/articles/Introduction.html#fields-containing-reference-objects talks about in "Fields containing reference objects". – user1700890 Apr 12 '21 at 20:06
  • Can I avoid using `private`? – user1700890 Apr 12 '21 at 21:04
  • 1
    @user1700890 yes. It is not necessary to define `shared_env` as a private field. However, if you make the field public, the counter can be overwritten by the client code. About the link: Yes, this is exactly the mechanism that is used in this solution. Normally, you want to initialize reference objects in `initialize()` but not doing so allows "shared-memory" between siblings. – Gregor de Cillia Apr 23 '21 at 16:54