2016-10-07 21 views
0

如何更新R6类实例的方法定义?更新R6对象实例中的方法定义

S3使用当前的方法定义,如我所料。 使用R5(引用类)我可以使用myInstance = myInstance $ copy()。 与R6我试着myInstance = myInstance $克隆()但myInstance $ someMethod()仍然调用旧的代码。

我需要这个,当我从长时间运行的进程创建的转储加载对象实例。我想在长时间运行计算后调试并更改对象状态上的代码。因此,我不能只创建一个新实例并重新运行初始化。 甚至比R5复制方法(不更新对实例的引用更好)更好,它将是一种将类和当前所有超类的当前定义的行为(即方法定义)分配给实例的方法。

下面是一个例子:

library(R6) 

Person <- R6Class("Person", 
     lock_objects=FALSE, 
     public = list(
       name = NULL, 
       initialize = function(name = NA, hair = NA) { 
        self$name <- name 
        self$greet() 
       }, 
       greet = function() { 
        cat(paste0("Hello, my name is ", self$name, ".\n")) 
       } 
     ) 
) 

# create an instance 
thomas <- Person$new("Thomas","brown") 

# modify the behaviour of Person 
Person <- R6Class("Person", 
     lock_objects=FALSE, 
     public = list(
       name = NULL, 
       initialize = function(name = NA, hair = NA) { 
        self$name <- name 
        self$greet() 
       }, 
       greet = function() { 
        cat(paste0("Modified greet from ", self$name, ".\n")) 
       } 
     ) 
) 

t1 <- Person$new("t1") # greet function updated 
t2 <- thomas$clone() 
t2$greet()    # greet function not updated in thomas nor t2 
+1

[动态添加函数到r6类实例]的可能重复(https://stackoverflow.com/questions/26331030/dynamically-add-function-to-r6-class-instance) –

回答

0

我想出了下面的技巧。 从问题的代码继续,我设法改变的greet方法定义R6对象实例thomas

replacePublicR6Method <- function(r6Instance, fName, fun){ 
    selfEnv <- environment(r6Instance[[fName]])$self 
    properEnv <- environment(r6Instance[[fName]]) 
    unlockBinding(fName, selfEnv) 
    selfEnv[[fName]] <- fun 
    environment(selfEnv[[fName]]) <- properEnv 
    lockBinding(fName, selfEnv) 
} 

replacePublicR6Method(thomas, "greet", function(){ 
      cat(paste0("Modified greetings from ", self$name, ".\n")) 
     }) 

thomas$greet() 

我想结合被锁定的目的,而这种黑客脏。 向R向导提问:这种攻击可以打破R6类的其他行为吗?它会继续与未来版本的R6类一起工作吗?

为了在长时间运行计算之后在对象状态下进行一些代码修改,这应该是可以的。到目前为止,它也适用于子类的实例。