Search code examples
rr6

Changing cloning behavior in R6 classes


Suppose I have an R6 class and one of it's elements is an external pointer pointing to some C++ object.

So I have something like this:

myClass <- R6::R6Class(
  "myClass", 
  public = list(
    xp = NULL,
    initialize = function(x) {
      self$xp = cpp_fun_that_returns_a_pointer(x)
    }
  )
)

If I use myclass$clone() it will still point to the same myclass$xp. This will also happen if I do myclass$clone(deep = TRUE) since it doesn't know how to clone in the C++ side.

In this case I could use a custom deep_clone method...

But since in my use case it will always be wrong to clone the class without deep cloning it, I am wondering if it is possible to change the behavior of clone directly.

I tried just creating a clone() method and it's not allowed by R6.

Error in R6::R6Class("tensor", cloneable = FALSE, private = list(xp = NULL),  : 
  Cannot add a member with reserved name 'clone'.

Solution

  • You can define a custom clone() method if you use cloneable = FALSE. I'm not sure what all you're doing with XPtrs, so I'll demonstrate a slightly simpler example:

    # Set up the R6 class, making sure to set cloneable to FALSE
    myClass <- R6::R6Class(
        "myClass", 
        public = list(
            xp = NULL,
            initialize = function(x = 1:3) {
                self$xp = x
            }
        ),
        cloneable = FALSE
    )
    # Set the clone method
    myClass$set("public", "clone", function() {
        print("This is a custom clone method!") # Test print statement
        myClass$new(self$xp)
    })
    # Make a new myClass object
    a <- myClass$new(x = 4:6)
    # Examine it
    a
    #> <myClass>
    #>   Public:
    #>     clone: function () 
    #>     initialize: function (x = 1:3) 
    #>     xp: 4 5 6
    # Clone it
    b <- a$clone()
    #> [1] "This is a custom clone method!"
    # We see the test print statement was printed!
    # Let's check out b:
    b
    #> <myClass>
    #>   Public:
    #>     clone: function () 
    #>     initialize: function (x = 1:3) 
    #>     xp: 4 5 6
    

    Created on 2019-02-05 by the reprex package (v0.2.1)