R R6类和UseMethod /泛型方法

Wor*_*yth 5 oop generics r class

我想使用R6类和泛型方法(UseMethod)将不同类(Small1,MyClassA和Small2,MyClassB)的小对象添加到MyClass的Big实例内的公共列表(MyListA和MyListB).

这适用于创建(Big是使用Small1和-2创建的),但之后失败:

> Big$AddObj(Small3) #produces:
Error in UseMethod("AddObj", x) :    no applicable method for 'AddObj'
 applied to an object of class "c('MyClassA', 'R6')"
Run Code Online (Sandbox Code Playgroud)

我不太确定我的错误是什么.以后如何为其他对象调用AddObj-Method?建议将非常感谢.

require('R6')

MyClass <- R6Class("MyClass",
   public = list(
     initialize = function(...) {
       for (x in list(...)) {AddObj(x)}
     },
     AddObj = function(x) {UseMethod("AddObj", x)},
     AddObj.MyClassA = function(x) {
       MyListA <<- c(MyListA, list(x))},
     AddObj.MyClassB = function(x) {
       MyListB <<- c(MyListB, list(x))},
     AddObj.default = function(x) {
       otherObjects <<- c(otherObjects, list(x))},
     Show = function() {
       print(methods(AddObj))
       if (length(MyListA)>0) print(MyListA)
       if (length(MyListB)>0) print(MyListB)
     },
     MyListA = list(),
     MyListB = list(),
     otherObjects = list()
   )
)

MyClassA <- R6Class("MyClassA",
  public = list(
    name = NA,
    initialize = function(input) {
      if (!missing(input)) name <<- as.character(input)}
  ))
MyClassB <- R6Class("MyClassB",
  public = list(
    name = NA,
    initialize = function(input) {
      if (!missing(input)) name <<- as.character(input)}
  ))


Small1 <- MyClassA$new("MyName1")
Small2 <- MyClassB$new("MyName2")
Big <- MyClass$new(Small1, Small2)
Big$Show()

Small3 <- MyClassA$new("MyNewName")
Big$AddObj(Small3)
Run Code Online (Sandbox Code Playgroud)

wch*_*wch 8

R6对象中没有S3调度,但您可以使用if-else语句,如下所示:

library('R6')

MyClass <- R6Class("MyClass",
  portable = FALSE,
  public = list(
    initialize = function(...) {
      for (x in list(...)) {AddObj(x)}
    },
    AddObj = function(x) {
      if (inherits(x, "MyClassA"))
        MyListA <<- c(MyListA, list(x))
      else if (inherits(x, "MyClassB"))
        MyListB <<- c(MyListB, list(x))
      else
        otherObjects <<- c(otherObjects, list(x))
    },
    Show = function() {
      if (length(MyListA)>0) print(MyListA)
      if (length(MyListB)>0) print(MyListB)
    },
    MyListA = list(),
    MyListB = list(),
    otherObjects = list()
  )
)

MyClassA <- R6Class("MyClassA",
  portable = FALSE,
  public = list(
    name = NA,
    initialize = function(input) {
      if (!missing(input)) name <<- as.character(input)}
  ))
MyClassB <- R6Class("MyClassB",
  portable = FALSE,
  public = list(
    name = NA,
    initialize = function(input) {
      if (!missing(input)) name <<- as.character(input)}
  ))



Small1 <- MyClassA$new("MyName1")
Small2 <- MyClassB$new("MyName2")
Big <- MyClass$new(Small1, Small2)
Big$Show()

Small3 <- MyClassA$new("MyNewName")
Big$AddObj(Small3)
Big$Show()
Run Code Online (Sandbox Code Playgroud)

另请注意,我使用了portable=FALSE设置,这是刚刚添加到R6开发版本的设置.有关详细信息,请参阅https://github.com/wch/R6/issues/16.

更新:事实证明我有点错误 - 在R6对象中有S3调度,但如果调用该函数,则不会使用它$,如Big$AddObj(Small3).你可以用以下的东西来利用它eval(quote(AddObj(Small3)), envir = Big),但这显然不是很好.最好使用if-else和use inherits().