Rappster
Rappster

Reputation: 13070

Manual modifications of the class definition of a Reference Class instance

I'm aware that this would be a terribly unreliable hack. But out of pure interest:

What would you need to manually change in the .refClassDef field of an ref class object if the Reference Class definition of an already instantiated object changed and you would like it to "be informed about the update" (without re-instantiating it).

After all, it does seem to work if additional methods are introduced, but not for modifications of existing methods (see example below).

This question is related to my answer in this post.


Example

Original class def:

MyReferenceClass <- setRefClass("MyReferenceClass",
    methods = list(
        print_hello = function(){
            print("hello")
        }
    )
)

Instantiate:

my_object <- MyReferenceClass$new()
my_object$print_hello()
[1] "hello"

Updated class def:

MyReferenceClass <- setRefClass("MyReferenceClass",
    methods = list(
        print_hello = function(){
            print("hello_again")
        },
        print_goodbye = function(){
            print("goodbye")
        }
    )
)

Instance can use the new method:

my_object$print_goodbye()
[1] "goodbye"

But it would for example fail to be informed about changes in print_hello as this post illustrates.

Upvotes: 2

Views: 178

Answers (1)

xb.
xb.

Reputation: 1677

Include an update method in your class (before and after modification). Call obj$update() before calling another method upon any updates of the class.

MyReferenceClass <- setRefClass(
  "MyReferenceClass",
  methods = list(
    print_hello = function(){
      print("hello")
    },
    update = function(){
      selfEnv <- as.environment(.self)
      .class <- as.character(class(.self))
      for (e in as.vector(utils::lsf.str(selfEnv))){ 
        v <- get(e,eval(parse(text=sprintf("%s@generator$def@refMethods",.class))))
        assign(e,v,envir=selfEnv)
      }
    }
    )
  )

UPDATE: Wed Jun 11 The update method now asks for a vector of methods to be updated, to avoid accidentally changes of internal methods. Thanks to @Rappster for pointing this out.

MyReferenceClass <- setRefClass(
  "MyReferenceClass",
  methods = list(
    print_hello = function(){
      print("hello")
    },
    update = function(x){
      selfEnv <- as.environment(.self)
      .class <- as.character(class(.self))
      for (e in x){
        v <- get(e,eval(parse(text=sprintf("%s@generator$def@refMethods",.class))))
        assign(e,v,envir=selfEnv)
      }
    }
    )
  )

obj <- MyReferenceClass$new()
obj$print_hello()

## ...
obj$update('print_hello')

Upvotes: 1

Related Questions