[Rd] Ref Classes: bug with using '.self' within initialize methods?

John Chambers jmc at r-project.org
Sat Jul 2 22:43:16 CEST 2011


I don't have anything to suggest on your specific example but perhaps 
these two notes are relevant.

1. As is mentioned in the documentation, it's generally a bad idea to 
write S4 initialize() methods for reference classes, rather than 
reference class methods for $initialize():
   "a reference method is recommended rather than a method for the S4 
generic function initialize(), because some special initialization is 
required for reference objects _before_ the initialization of fields."



2. In a simple example, there is no problem using .self in a 
$initialize() method.

######
ss <- setRefClass("ss", fields = c("a", "b", "c"),
     methods = list(
         initialize = function(...) {
             callSuper(...)
             .self$b <- .self$a
         },
         check = function()
              .self$c <- .self$a
     ))

s1 <- ss$new(a=1)
s1$check()
stopifnot(identical(s1$a, 1), identical(s1$a, s1$b),
           identical(s1$a, s1$c))
#######

On 6/29/11 9:36 AM, Janko Thyson wrote:
> Dear list,
>
> I'm wondering if the following error I'm getting is a small bug in the
> Reference Class paradigm or if it makes perfect sense.
>
> When you write an explicit initialize method for a Ref Class, can you
> then make use of '.self' WITHIN this initialize method just as you would
> once an object of the class has actually been initialized?
> Because it seems to me that you can not.
>
> Below is an example that shows that calling '.self$someInitFoo()' within
> the initialize method for 'MyClass' does not work (see section "METHODS"
> in example below). Instead I have to go with
> 'someInitFooRefInner(.self=.Object, ...)' (see section "UPDATED METHOD"
> in example below). Yet, this is only possible because there actually IS
> such a method (I try to stick to the recommendations at ?setRefClass
> where it says: "Reference methods should be kept simple; if they need to
> do some specialized *R* computation, that computation should use a
> separate *R* function that is called from the reference method")
>
> The same problem occurs when, say 'someInitFoo()' calls yet another Ref
> Class method (as is the case in the example below with a call to
> '.self$someFoo()').
>
> Is this a desired behavior?
>
> Thanks for any clarifying comments!
> Janko
>
> ##### CODE EXAMPLE #####
>
> # CLASSES
> setRefClass(
>       Class="MyVirtual",
>       contains=c("VIRTUAL"),
>       methods=list(
>           initialize=function(...){
>               callSuper(...)
>               return(.self)
>           },
>           someInitFoo=function(flds, ...){
>               someInitFooRefInner(
>                   .self=.self,
>                   flds=flds
>               )
>           }
>       )
> )
> GENERATOR<- setRefClass(
>       Class="MyClass",
>       contains=c("MyVirtual"),
>       fields=list(
>           A="character",
>           B="numeric"
>       ),
>       methods=list(
>           someFoo=function(...){
>               someFooRefInner(.self=.self, ...)
>           }
>       )
> )
> # /
>
> # GENERICS
> setGeneric(name="someInitFooRefInner",
>       def=function(.self, ...) standardGeneric("someInitFooRefInner"),
>       signature=c(".self")
> )
> setGeneric(name="someFooRefInner",
>       def=function(.self, ...) standardGeneric("someFooRefInner"),
>       signature=c(".self")
> )
> # /
>
> # METHODS
> setMethod(
>       f="someInitFooRefInner",
>       signature=signature(.self="MyVirtual"),
>       definition=function(.self, flds, ...){
>           print("Trying to call '.self$someFoo()")
>           try(.self$someFoo())
>           print("Trying to call 'someFooRefInner(.self=.self)")
>           try(someFooRefInner(.self=.self))
>           return(flds)
>       }
> )
> setMethod(
>       f="someFooRefInner",
>       signature=signature(.self="MyVirtual"),
>       definition=function(.self, ...){
>           print("hello world!")
>       }
> )
> setMethod(
>       f="initialize",
>       signature=signature(.Object="MyVirtual"),
>       definition=function(.Object, GENERATOR=NULL, ...){
>           # MESSAGE
>           if(class(.Object) == "MyVirtual"){
>               cat(paste("initializing object of class '", class(.Object),
> "'",
>                   sep=""), sep="\n")
>           } else {
>               cat(paste("initializig object of class'", class(.Object),
>                   "' inheriting from class 'MyVirtual'", sep=""), sep="\n")
>           }
>           # /
>           # GET GENERATOR OBJECT
>           if(is.null(GENERATOR)){
>               GENERATOR<- getRefClass(class(.Object))
>           }
>           flds<- names(GENERATOR$fields())
>           .Object$someInitFoo(
>               flds=flds,
>               ...
>           )
>           return(.Object)
>       }
> )
> # /
>
> x<- GENERATOR$new()
>
> # UPDATED METHOD
> setMethod(
>       f="initialize",
>       signature=signature(.Object="MyVirtual"),
>       definition=function(.Object, GENERATOR=NULL, ...){
>           # MESSAGE
>           if(class(.Object) == "MyVirtual"){
>               cat(paste("initializing object of class '", class(.Object),
> "'",
>                       sep=""), sep="\n")
>           } else {
>               cat(paste("initializig object of class'", class(.Object),
>                       "' inheriting from class 'MyVirtual'", sep=""),
> sep="\n")
>           }
>           # /
>           # GET GENERATOR OBJECT
>           if(is.null(GENERATOR)){
>               GENERATOR<- getRefClass(class(.Object))
>           }
>           flds<- names(GENERATOR$fields())
>           someInitFooRefInner(.self=.Object, flds=flds, ...)
>           return(.Object)
>       }
> )
> # /
>
> x<- GENERATOR$new()
>
> 	[[alternative HTML version deleted]]
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



More information about the R-devel mailing list