2

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).

mjv
  • 73,152
  • 14
  • 113
  • 156
Mark Graph
  • 4,969
  • 6
  • 25
  • 37
  • 2. doesn't seem at all quirky/strange to me - that's just standard R environment semantics. But I think you misunderstand what's going on - because you've assigned to `me.static.private` in the global environment – hadley Nov 09 '12 at 13:25
  • 1
    And in 3. I don't think you need `<<-` - you're just assigning to a specified variable `me.private` in a specified environment `.self` – hadley Nov 09 '12 at 13:26
  • Hadley - once again, thank you for your insight - on #2 you are right, the `me.static.private` variable is in the global environment. It can be seen there using ls() - on #3, I think `<<-` and `<-` write to the same place (not sure why), but my tests indicate this (and I am left wondering if a different result would occur with a subclass). – Mark Graph Nov 09 '12 at 21:35
  • They write to the same place because you've specified the environment (`.self`). I don't think using a subclass would be different because I don't think the environments will be nested. – hadley Nov 10 '12 at 13:21
  • See related question: https://stackoverflow.com/questions/8159317/private-members-in-r-reference-class – mjv Oct 15 '14 at 22:30

1 Answers1

1

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

Mark Graph
  • 4,969
  • 6
  • 25
  • 37