The goal of staticRef is to add static and private variable and methods support for R reference classes.
You can install the released version of extendedRef from CRAN with:
install.packages("extendedRef")To setup an extended reference class use the setExtendedRefClass() function. For this example we will create a registered counter class that tracks all the counters created and the individual counts.
counter<- setExtendedRefClass('registeredCounter',
# fields define the publicly accessible fields, same as setRefClassfields= c(name='character'),
# private are the variables that are not accessible via the `$` operatorprivate= c(count='integer'),
# staic specifies static variables common to all variables.static= c( counters='list' ),
# static.const specifies constants for the class that cannot be changed.# since these do not change they are specified once by a list with the # values they should take.static.const=list( max=3L),
# for illustration, we are artificially setting a maximum of 3 counters # Methods are specified with lists of functions.# static methodsstatic.methods=list( how_many_counters=function()length(counters)
, add_counter=function(counter){
x<-list(counter)
names(x) <-counter$namecounters<<- c(counters, x)
}),
# private methodsprivate.methods=list(private_initialize=function(){
# The public initialize, cannot use or alter private variables,# the `private_initialize` function serves this role. count<<-0L# The private initialize can also access the static variables,if (how_many_counters() <max) add_counter(.self) else
stop("Cannot create another counter!")
}),
# methods as with setRefClass defines the public methods.methods=list( increment=function()count<<-count+1L
, get_count=function()count
)
# note that the public function alters a 'private' variable.
)This class may not be very useful but illustrates the concepts.
As before the counter object is a object generator function that creates objects from the exteneded reference class 'registeredCounter'. However, the generator object also provides a method for accessing the static variables and methods.
counter$static$how_many_counters()
#> [1] 0counter$static$max#> [1] 3first<- counter(name='first')We now have first as a counter and we have one counter registered.
first$get_count()
#> [1] 0counter$static$how_many_counters()
#> [1] 1Counter is a reference class so you can do all the things that you would do with a reference class
first$increment()
first$get_count()
#> [1] 1also.first<-firstalso.first$get_count()
#> [1] 1Note that one thing you cannot do is access the private variable count.
first$count#> Error in envRefInferField(x, what, getClass(class(x)), selfEnv): 'count' is not a valid field or method name for reference class "registeredCounter"For the static variables all object have access to them from their internal methods, but not publicly.
first$how_many_counters()
#> Error in envRefInferField(x, what, getClass(class(x)), selfEnv): 'how_many_counters' is not a valid field or method name for reference class "registeredCounter"Let's create a few more counters.
second<- counter(name='second')
third<- counter(name='third')
fourth<- counter(name='fourth')
#> Error in private.methods$private_initialize(): Cannot create another counter!We cannot add the fourth counter because we specified that we can only have 3 total.
counter$static$how_many_counters()
#> [1] 3Since the counters are registered we can retrieve them from the registry.
counter$static$counters[['first']]$get_count()
#> [1] 1The static variables are tied to the stored definition so there is always only one copy.
validate_that(identical(counter$def, getClass('registeredCounter')))
#> [1] TRUE