定义调用R6对象之外的其他方法的方法

时间:2016-01-30 23:35:41

标签: r oop r6

使用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)出错:找不到对象'private'

2 个答案:

答案 0 :(得分:2)

您面临的问题是您定义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然后在顶级环境中都有自己的名称但不起作用 - 它们实际上只在类定义中有意义。如果您感兴趣的是代码重用,我认为对象组合或继承会不那么令人惊讶。

答案 1 :(得分:1)

首先,让我们把这个例子简化下来,然后再说一遍:

# 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传递给子函数 - 因为父函数显然可以看到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