2

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.

Community
  • 1
  • 1
Rappster
  • 12,762
  • 7
  • 71
  • 120

1 Answers1

1

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')
xb.
  • 1,617
  • 11
  • 16
  • Nice approach! But I think the manual assignment destroys the internal self-referencing structure: once you ran `update()`, none of the methods are able to use/find `.self` anymore in subsequent calls. Just try running `update()` twice in a row. Any idea on how to fix that? – Rappster Apr 04 '14 at 13:26
  • @Rappster Sorry for coming back late. And yes, there are indeed some conflicts when making `update` in a blind manner, due to changes in internal methods. I will update the code to only allow updates on custom-specified methods. – xb. Jun 11 '14 at 16:08