如何更新R6类实例的方法定义?
S3正如我所料,使用当前的方法定义。 使用R5(参考类),我可以使用myInstance = myInstance $ copy()。 使用R6我尝试了myInstance = myInstance $ clone(),但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
答案 0 :(得分:0)
我提出了以下黑客攻击。
继续问题中的代码,我设法更改了R6对象实例greet
中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-Wizards的提问:这个hack能破坏R6类的其他一些行为吗?它会继续使用未来版本的R6类吗?
为了在长时间运行的计算之后尝试在对象状态下进行一些代码修改,这应该没问题。到目前为止,它还适用于子类的实例。
答案 1 :(得分:0)
此问题有一个简单的解决方法。将类方法的默认值设置为NULL
,并在initialize()
方法中更新此值。现在,您可以根据需要更改方法,而不会收到此错误。例如:
aClass <- R6::R6Class("className",
public = list(
f = NULL,
initialize = function(...) {
self$f = sum
},
update_f = function(x) {
self$f = x
}
)
)
test <- aClass$new()
test$f
test$update_f(mean)
test$f
或者,您可以就地修改该功能:
test$f <- median
test$f
那应该可以解决问题。我还发布了此答案here。