2

In large projects I sometime want to have a standardized and rigid data 'object' such that any function of that data may confidently assume numerous properties of the object with no more than an assertion that the object is of the expected class. So I'm very happy to have discovered R6 classes, which seem to allow this by providing 'private' elements as follows:

library('R6')
Data = R6::R6Class("Data", 
    private = list(x = NA, y = pi),
    public = list(
        initialize = function(x, y) {
            private$x = x
        },
        get = function(attribute) return(private[[attribute]])
    )
)

data = Data$new(x = 5)
data$get('x')
data$get('y')

This get function is a hack. What I really want is for the attributes of data to be accessible simply as data$x or data[['x']] while still having the tamper-proof qualities of private variables. Is there a better way to achieve this?

zkurtz
  • 3,230
  • 7
  • 28
  • 64
  • This discussion seems to indicate that there is no significantly easier way to do it: https://github.com/r-lib/R6/issues/41 – zkurtz May 08 '18 at 13:33

1 Answers1

2

I'll briefly summarize what I learned here. The base::lockBinding function is applicable here because an R6 class is essentially an environment:

library('R6')
Data = R6::R6Class("Data", 
    public = list(
        x = NA,
        y = pi,
        initialize = function(x) {
            self$x = x
            lockBinding("x", self)
            lockBinding("y", self)
        }
    )
)

data = Data$new(x = 5)
data$x
data$y

Since x and y are locked, data$x = 5 throws an error, as desired.

zkurtz
  • 3,230
  • 7
  • 28
  • 64