我试图忘记refclasses(R5)并转移到R6,但动态代码存在问题。我会添加一个新函数,它在R5中起作用:
clsTrn <- setRefClass("clsTrn",
fields = list(x = "numeric"),
methods = list(
add_function = function(rcode) {
eval(parse(text=rcode), envir=.self)
}
)
)
cls <- clsTrn$new(x=4)
cls$x
# [1] 4
cls$add_function("predict = function(y) {return(.self$x*y)}")
cls$predict(3)
#[1] 12
类似的代码对R6不起作用。
library(R6)
clsTrnR6 <- R6Class("clsTrnR6",
lock=FALSE,
public = list(
x = NA,
initialize = function(x) {
self$x <- x
},
add_function = function(rcode) {
eval(parse(text=rcode), envir=self)
}
)
)
clsR6 <- clsTrnR6$new(x=4)
clsR6$x
#[1] 4
clsR6$add_function("predict = function(y) {return(self$x*y)}")
# Błąd weval(expr, envir, enclos) : nie udało się znaleźć funkcji '='
clsR6$predict(3)
在类定义中添加预测什么都不会改变,同样的错误。 有什么解决方案吗?提前致谢。
> sessionInfo()
R version 3.1.1 (2014-07-10)
Platform: x86_64-pc-linux-gnu (64-bit)
locale:
[1] LC_CTYPE=pl_PL.UTF-8 LC_NUMERIC=C LC_TIME=pl_PL.UTF-8 LC_COLLATE=pl_PL.UTF-8 LC_MONETARY=pl_PL.UTF-8
[6] LC_MESSAGES=pl_PL.UTF-8 LC_PAPER=pl_PL.UTF-8 LC_NAME=C LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=pl_PL.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] R6_2.0
loaded via a namespace (and not attached):
[1] codetools_0.2-8 rpart_4.1-5 tools_3.1.1
>
已添加:在伟大的@ G.Grothendieck回答之后,我有基于字符串的功能定义,但也许有更优雅的解决方案。
library(R6)
clsTrnR6 <- R6Class("clsTrnR6",
lock=FALSE,
public = list(
x = NA,
initialize = function(x) {
self$x <- x
},
add_function = function(name, meth) {
self[[name]] <- meth
environment(self[[name]]) <- environment(self$add_function)
},
add_function2 = function(name, meth) {
eval(parse(text=paste0("predict <- ",meth)))
self[[name]] <- predict
environment(self[[name]]) <- environment(self$add_function)
}
)
)
clsR6 <- clsTrnR6$new(x=4)
clsR6$x
#[1] 4
clsR6$add_function2("predict", "function(y) y*self$x")
clsR6$predict(11)
#[1] 44
答案 0 :(得分:6)
试试这个。与引用类示例一样,它向对象(而不是类)添加了一个函数。这里name
是一个包含函数/方法名称的字符串,meth
是函数/方法本身:
clsTrnR6 <- R6Class("clsTrnR6",
lock=FALSE,
public = list(
x = NA,
initialize = function(x) {
self$x <- x
},
add_function = function(name, meth) {
self[[name]] <- meth
environment(self[[name]]) <- environment(self$add_function)
}
)
)
clsR6 <- clsTrnR6$new(x=4)
clsR6$x
#[1] 4
clsR6$add_function("predict", function(y) y*self$x)
clsR6$predict(11)
## 44
已添加请注意,使用proto也很容易。它不需要特殊的add_function
。我们将使用大写P
来表示扮演类角色的proto对象(在proto vignette中称为“Trait”),并使用小写p
来表示扮演的proto对象实例的作用:
library(proto)
P <- proto(new = function(., x) proto(x = x))
p <- P$new(x = 4)
p$predict <- function(., y) .$x * y
p$predict(11)
## 44
虽然使用.
引用proto中的对象很常见,但如果您愿意,可以使用名称self
(或任何您喜欢的名称)代替.
。< / p>
答案 1 :(得分:4)
您可以在生成器对象上使用$set() method
。因此,您将更改类定义而不是对象。
clsTrnR6$set("public", "predict", function(y) self$x*y)
clsR6 <- clsTrnR6$new(x=4)
clsR6$predict(3)
[1] 12
更改类定义意味着在使用$ set修饰符之前创建的对象将不具有predict
函数。
答案 2 :(得分: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。