dynamically add function to r6 class instance

梦想与她 提交于 2019-11-28 08:43:33

Try this. Like the reference class example it adds a function to the object (not the class). Here name is a character string containing the name of the function/method and meth is the function/method itself:

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

Added Note that this is also easy to do using proto. It does not require a special add_function. We will use an upper case P to denote the proto object that plays the role of a class (called a "Trait" in the proto vignette) and use lower case p to denote the proto object that plays the role of an instance:

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

Although its common to use . to refer to the object in proto you can use the name self (or any name you like) in place of . if you prefer.

You can use $set() method on the generator object. So you will change the class definition not the object.

clsTrnR6$set("public", "predict", function(y) self$x*y)
clsR6 <- clsTrnR6$new(x=4)
clsR6$predict(3)
[1] 12

Edit:

Changing the class definition means that the object created prior to using the $set modifier will not have the predict function.

There is a simple workaround for this problem. Set the default value of the class method to NULL and update this value within the initialize() method. Now, you can change the method as you like without receiving this error. For example:

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

Or, one can modify the function in-place:

test$f <- median
test$f

That should resolve the issue. I also posted this answer here.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!