When using R6 classes, what is the proper way to define methods outside of the class that call other methods?
Consider the following example, where the function func
might dispatch to another function if it is being used interactively. But, if it does so, the other function doesn't have access to the private environment. Should I be passing an environment around if I define classes this way?
## 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'
Error in ifunc() (from #3) : object 'private' not found
The problem you are facing is that you define func
and ifunc
in such a way that the implementation only makes sense inside the class definition - but not completely. You are getting an error because ifunc
is implemented as if it knows about the internals of your class (it refers to private), but it doesn't. You never actually include it into your class definition. So you have to refer in func
to the private member function ifunc
and include ifunc
into the class:
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
)
)
However, I must say that I don't understand this strategy. The functions func
and ifunc
then both have their own names in a top level environment but don't work - they really only make sense in the class definition. If code reuse is what you are interested in I think object composition or inheritance would be less surprising.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With