【问题标题】:Defining methods that call other methods outside of R6 objects定义调用 R6 对象之外的其他方法的方法
【发布时间】:2016-01-30 23:35:40
【问题描述】:

使用 R6 类时,在类之外定义调用其他方法的方法的正确方法是什么?

考虑以下示例,如果函数func 以交互方式使用,它可能会分派给另一个函数。但是,如果这样做,则其他功能无法访问私有环境。如果我以这种方式定义类,是否应该传递环境?

## General function defined outside R6 class
func <- function(x) {
  if (missing(x) && interactive()) {
    ifunc()
  } else {
    private$a <- x * x
  }
}

## If interactive, redirect to this function
ifunc <- function() {
  f <- switch(menu(c('*', '+')), '1'=`*`, '2'=`+`)
  private$a <- f(private$a, private$a)
}

## R6 test object
Obj <- R6::R6Class("Obj",
  public=list(
    initialize=function(a) private$a <- a,
    geta=function() private$a,
    func=func  # defined in another file
  ),
  private=list(
    a=NA
  )
)

## Testing
tst <- Obj$new(5)
tst$func(3)
tst$geta()  # so func sees 'private'
# [1] 9

tst$func()  # doesn't see 'private'

ifunc() 中的错误(来自 #3):找不到对象“私有”

【问题讨论】:

    标签: r oop r6


    【解决方案1】:

    您面临的问题是您定义funcifunc 的方式使得实现只在类定义中有意义——但并不完全。你得到一个错误,因为ifunc 的实现好像它知道你的类的内部(它指的是私有的),但它不知道。你从来没有真正将它包含在你的类定义中。所以你必须在func 中引用私有成员函数ifunc 并将ifunc 包含到类中:

    func <- function(x) {
        if (missing(x) && interactive()) {
            private$ifunc()
        } else {
            private$a <- x * x
        }
    }
    
    
    ifunc <- function() {
        f <- switch(menu(c('*', '+')), '1'=`*`, '2'=`+`)
        private$a <- f(private$a, private$a)
    }
    
    
    Obj <- R6::R6Class(
        "Obj",
        public=list(
            initialize=function(a) private$a <- a,
            geta=function() private$a,
            func=func  # defined in another file
        ),
        private=list(
            a=NA,
            ifunc=ifunc
        )
    )
    

    但是,我必须说我不了解这种策略。 funcifunc 函数在顶级环境中都有自己的名称,但不起作用 - 它们实际上只在类定义中有意义。如果您对代码重用感兴趣,我认为对象组合或继承就不会那么令人惊讶了。

    【讨论】:

    • 我认为 R.oo 和 proto 包会支持您正在寻找的东西:您不必在类定义中定义所有成员。但可能你会在 R6 中失去一些你喜欢的功能......
    【解决方案2】:

    首先,让我们把这个例子简化一下,让它更有说服力:

    # function defined outside R6 class
    parent_function <- function(x) {
      if (missing(x)) {
        child_function()
      } else {
        self$a <- x * x
      }
    }
    
    # function called by previous function
    child_function <- function() {
      self$a <- 999999
    }
    
    # R6 test object
    my_object <- R6::R6Class(
      "my_object",
      public=list(
        func=parent_function,
        a=1
      )
    )
    
    
    # Testing
    tst <- my_object$new()
    tst
    
    ## <my_object>
    ## Public:
    ## a: 1
    ## clone: function (deep = FALSE) 
    ## func: function (x) 
    
    
    tst$func(8)
    tst$a
    
    ## [1] 64
    
    
    tst$func()
    
    ## Error in self$a <- 999999 : object 'self' not found
    

    现在的想法是self 传递给子函数 - 因为父函数显然可以看到自己,所以它可以传递它

    # General function defined outside R6 class
    parent_function <- function(x) {
      if (missing(x)) {
        child_function(self)
      } else {
        self$a <- x * x
      }
    }
    
    # If interactive, redirect to this function
    child_function <- function(self) {
      self$a <- 999999
    }
    
    # R6 test object
    my_object <- R6::R6Class(
      "my_object",
      public = 
        list(
          func=parent_function,
          a=1
        ),
    )
    
    ## Testing
    tst <- my_object$new()
    tst
    
    ## <my_object>
    ## Public:
    ## a: 1
    ## clone: function (deep = FALSE) 
    ## func: function (x) 
    
    
    tst$func(8)
    tst$a
    
    ## [1] 64
    
    
    tst$func()  
    tst$a
    
    ## [1] 999999
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多