Question

I have been playing a little with R's R5 class system to see what it can and can't do. In that process I have stumbled upon what looks like static class field members (which does not appear to be in the documentation - but i could have missed it)

[2014 update]
Warning !!! : The following code does not work with R version >= 3.0
This post, its answers and particularly the comments provide useful insights and reminders about the R5 OO-system and the R language in general. However it is probably a bad idea to cultivate the idiom of using the environment of the R5 class instances directly.
[end 2014 update]

In the following code, the first field is the classic definition of an instance field variable. The second definition appears to create a static class field using an accessor method. I would like to know if this use is kosher (or is my code example simply coincidental). The third field use creates a quasi-private instant field variable using an accessor method.

assertClass <- function(x, className, R5check=FALSE) {
    # simple utility function
    stopifnot(class(x)[1] == className)
    if(R5check) stopifnot(is(x, 'envRefClass'))
}

A <- setRefClass('A',
    fields = list(
        # 1. public, typed, instance field
        myPublicInstanceVar = 'character',

        # 2. this assignment appears static
        #    but if the field me.static.private
        #    was declared in the field list
        #    it would be a local instance var
        myPrivateStaticVar = function(x) {
            if (!missing(x)) {
                assertClass(x, 'character')
                me.static.private <<- x
            }
            me.static.private
        },

        # 3. quasi-private, typed, instance field
        myPrivateInstanceVar = function(x) {
            if (!missing(x)) {
                assertClass(x, 'character')
                .self$me.private <<- x
            }
            .self$me.private
        }
    ),

    methods = list(
        initialize = function (c='default') {
            myPublicInstanceVar <<- c
            myPrivateStaticVar <<- c
            myPrivateInstanceVar <<- c
        }
    )
)

# test instantiation
instance1.of.A <- A$new('first instance')
str(instance1.of.A)

instance2.of.A <- A$new('second instance')
str(instance1.of.A)
str(instance2.of.A)

instance3.of.A <- getRefClass('A')$new('third instance')
instance3.of.A$myPrivateStaticVar <- 'Third instance - changed'
print(instance1.of.A$myPrivateStaticVar)
print(instance2.of.A$myPrivateStaticVar)
print(instance3.of.A$myPrivateStaticVar)
str(instance1.of.A)
str(instance2.of.A)
str(instance3.of.A)

# but not really private ...
instance1.of.A$myPublicInstanceVar # works
instance1.of.A$me.static.private   # DOES NOT WORK - where is this variable stored 
instance1.of.A$me.private          # works

# till death do us part
instance3.of.A <- NULL
gc()
str(instance1.of.A)
str(instance2.of.A)
str(instance3.of.A)

If you run this code - you can see that the second field variable appears to operate as a static class member. What is less clear to me is where the reference class keeps this field (hence my comment in the penultimate line above).

Was it helpful?

Solution

The short answer - based on Hadley's comments above - is no. R's reference classes do not have static variables.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top