Update a Reference Class method

963 Views Asked by At

I am currently developping Reference classes (R5) for large objects which take time to produce, and i wonder if someone knows a better way to develop methods than redefining the class with setRefClass and reproduce an object each time i update a method.

In other words : can the methods of an existing Reference class object be redefined ?

2

There are 2 best solutions below

0
On

I had considered doing the following:

test <- setRefClass("TEST",
              fields = list(a = "numeric"),
              methods = list(
                        funA = function(){
                                      a <<- a+1
                                     },
                        initialize = function(){
                                          a <<- 1
                                          callSuper()
                                         }
                        )
)

ex1 <- test$new()

ex1$funA()

test$methods(funA = function(){
                      a <<- a+10
                     }
            )

ex$funA
# Class method definition for method funA()
# function () 
# {
#     a <<- a + 1
# }
# <environment: 0x0537f8ac>

ex1 <- test$new()$import(ex1)

ex$funA
# Class method definition for method funA()
# function () 
# {
#     a <<- a + 10
# }
# <environment: 0x04badc5c>

I believe you can overwrite the previous method in the class using class$methods( , then you can set a new object from your redefined class and import the old object. I would note:

"All methods for a class should be defined in the source code that defines the class, typically as part of a package. In particular, methods can not be redefined in a class in an attached package with a namespace: The class method checks for a locked binding of the class definition." from ?setRefClass also.

0
On

This problem bothered me for months now. Today I found a very handy solution inspired by https://stat.ethz.ch/pipermail/r-help/2012-January/299743.html

Let's start with a ReferenceClass which has an erroneous implementation:

MyClass <- setRefClass(
  "MyClass",
  fields = list(
    xy = "data.frame"
  ),
  methods = list(
    initialize = function( df ){
      if( !missing( df ) ){
        xy <<- df
      }
    },
    getSecondRow = function(){
      # A mistake happend here
      return( xy[1,] )
    }
  )
)

mc <- MyClass$new( data.frame( a = 1:10, b = rnorm(10) ) )
mc$getSecondRow()

  a         b
1 1 0.1349983

The implementation of getSecondRow does obviously not provide the desired result. So the fixed method should actually look like

    getSecondRow = function(){
      return( xy[2,] )
    }

Classes without explicit implementation of the constructor

The trick instead of loading the class and reproducing the object from scratch is to construct an new object from the existing, using the copy constructor functionality of the default initialize( ... ) constructor. After debugging and reloading the class you can just copy the existing object with the implementation into the same variable by

# NOTRUN
mc <- MyClass$new( mc )

Classes with overwritten constructor.

However, in the case presented here, the standard constructor is already overwritten. But in such cases you can simply use the functionality of callSuper( ... ) such that your constructor should look like

    initialize = function( df, ... ){
      callSuper( ... )
      if( !missing( df ) ){
        xy <<- df
      }
    }

Finally, your fixed object is derived by

mc <- MyClass$new( mc$xy, mc )
mc$getSecondRow()

  a         b
2 2 0.8452587