Search code examples
rr6

Initialize R6 class with an instance of Class and return the same Class


Given an R6 class Class1 with its initialize function, I would like to be able to pass an instance of the same class and return it directly.

Something like this:

if("Class1" %in% class(x)) x
else Class1$new(x)

But inside the initialize function of an R6 class, that should work like this

# This script does not work
# Definition of the class
Class1 = R6::R6Class("Class1",
                     public=list(
                       initialize = function(x){
                         # This line does not work
                         if("Class1"%in%class(x)) return(x)
                       }
                     ))
# Initiate an instance from scratch
foo = Class1$new()
# Initiate an instance through another instance
bar = Class1$new(foo)
# The two should be the same
identical(foo, bar)
#> TRUE

Solution

  • Under current state of R6 this seems to not be possible. Check the raw code github.com/r-lib/R6/blob/master/R/new.R . Most important are lines 154 where is initialization applied and 194 where public_bind_env is returned . The problem is that even with super assignment I think we could not overwrite it as all things are built here from a new empty env with own address. This solution which using a wrapper is widthly used in the market and it is doing what it should:

    class1 <- function(x = NULL) {
      
      if(inherits(x, "Class1")) x else Class1$new(x)
        
    }
    
    Class1 = R6::R6Class("Class1",
                         public=list(
                           initialize = function(x = NULL){
                           }
                         ))
    # Initiate an instance from scratch
    foo = class1()
    # Initiate an instance through another instance
    bar = class1(foo)
    # The two should be the same
    identical(foo, bar)
    #> TRUE