使用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'
答案 0 :(得分:2)
您面临的问题是您定义func
和ifunc
的方式是实现只在类定义中有意义 - 但不完全。您收到错误是因为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
)
)
但是,我必须说我不明白这个策略。函数func
和ifunc
然后在顶级环境中都有自己的名称但不起作用 - 它们实际上只在类定义中有意义。如果您感兴趣的是代码重用,我认为对象组合或继承会不那么令人惊讶。
答案 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