I'm looking for a way to tell an instance of a reference class to forget one of its method definitions. For example, I create the class MyReferenceClass
and an instance called my_object
I can call the method print_hello
and everything works:
MyReferenceClass <- setRefClass("MyReferenceClass",
methods = list(
print_hello = function(){
print("hello")
}
)
)
my_object <- MyReferenceClass$new()
my_object$print_hello() # "hello"
If I update the class definition by adding a new method (print_goodbye
) my existing object will be able to use it. But if I change a previously defined method (print_hello
), it won't update:
MyReferenceClass <- setRefClass("MyReferenceClass",
methods = list(
print_hello = function(){
print("hello_again")
},
print_goodbye = function(){
print("goodbye")
}
)
)
my_object$print_goodbye() # "goodbye" => it works
my_object$print_hello() # "hello" => it doesn't work
Is there a way to tell my_object
to forget about its definition of print_hello
? This doesn't work: my_object$print_hello <<- NULL
AFAIK the answer is no when trying to inform the object about the class def change "after the fact", i.e. after it has been instantiated/created.
Once you created an instance of a S4 Class, that object is "bound" to the class def as it was when you created the object. And in my opinion this makes perfect sense. Not sure if the "successful" update for formerly missing methods (i.e.
print_goodbye()
) simply works "by accident" or actually is the desired behavior.Recommended way to deal with updated class defs
My recommendation: if you decide you want/need to update your class defs, you're just safer off by re-sourcing your entire project code. That way you make sure everything is in place before you create actual instances. I'd consider anything else to be quite a hack that stands on very shaky grounds.
If you decide to hack anyway
There might be some dirty way to hack the hidden
.refClassDef
object field of an Reference Class instance that actually contains the class def (seemy_object$.refClassDef
). But setting this field (i.e. using<-
on it) didn't work:Neither did an explicit assignment via
assign()
:An even deeper hack would probably involve looking at
attributes(my_object$.refClassDef)
. There you might find the actual pieces that make up the ref class def. However, I don't know if even changing anything there would be "immediately" reflected.Also,
resetClass()
might give you some more insights.UPDATE: 2014-03-19
For handling your caching-approach two approaches come to mind:
1. The most evident way: use
copy()
See
?setRefClass
Before copying:
After copying:
2. Hacking at
attributes(my_object$.refClassDef)$refMethods
(OUTLINE, NOT WORKING YET)Even though I wouldn't recommend actually relying on something like this, hacks are always a great way to get a deeper understanding of how things work.
In this case, we could try to modify
attributes(my_object$.refClassDef)$refMethods
which is an environment that contains the actual method defs as I'm guessing that this is where the object "looks" when a method is called.It's no problem overwriting the actual method defs, yet it seems to have no immediate effect. I'm guessing that there are more "links" to the "old" class def involved that would need to be updated manually in a similar way.
Note that
my_object
still features the methodprint_hello
that prints"hello"
:This is how an overwriting function might look like:
Applying it:
Even though the def of
print_hello
was indeed overwritten, the object still grabs the "old" version somehow:Take advantage of my_class@generator$def@refMethods
How about including an
update
method in the original class, as did here,Manual modifications of the class definition of a Reference Class instance