5

使用 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):找不到对象“私有”

4

2 回答 2

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

于 2016-03-22T20:05:53.933 回答
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给子函数——因为父函数显然可以看到自己,所以它可以传递它

# 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
于 2016-06-17T11:50:34.893 回答