[R] Method dispatch in S4

Simon Zehnder simon.zehnder at googlemail.com
Sat Aug 3 21:43:01 CEST 2013


Dear R-Users and R-Devels,

I am struggling with the method dispatch for S4 objects. First I will give a simple example to make clear what the general setting in my project is. 

Three classes will be build in the example: A is just a simple class. B contains A in a slot and C inherits from B. In addition all classes have a slot called "specA", "specB", specC" that should be computed during initialization by calling the method "generateSpec" defined for each class A,B,C:

## Define class A##
setClass("A", representation(a = "numeric", specA = "numeric"))
setMethod("initialize", "A", function(.Object, value){.Object at a <- value; .Object <- generateSpec(.Object); return(.Object)})
setGeneric("generateSpec", function(object) standardGeneric("generateSpec"))
setMethod("generateSpec", "A", function(object) {object at specA <- 1/object at a; return(object)})

## Define class B containing A in a slot ##
setClass("B", representation(b = "numeric", specB = "numeric", A = "A"))
setMethod("initialize", "B", function(.Object, value = 0){.Object at b <- value; .Object at A <- new("A", value = value); .Object <- generateSpec(.Object); return(.Object)})
setMethod("generateSpec", "B", function(object) {aSpec <- object at A@specA; object at specB <- 1/aSpec; return(object)})
## all fine:
new("B", value = 2)

## Define class C inheriting from class B ##
setClass("C", representation(c = "numeric", specC = "numeric"), contains=c("B"))
setMethod("initialize", "C", function(.Object, value) {.Object at c <- value; .Object <- callNextMethod(.Object, value); .Object <- generateSpec(.Object); return(.Object)})
setMethod("generateSpec", "C", function(object) {bSpec <- object at specB; object at specC <- 1/bSpec; return(object)})
## numeric(0) for specB and specC
new("C", value = 2)

Note, that the "generateSpec" method of B depends on the "specA" slot of A, the "generateSpec" method of class C depends on the "specB" slot of class B. Note also, that in the "initialize" method of B one has to give the "value" argument a default value. When calling the last line of code, "specB" and "specC" are numeric(0). As the slot "b" of the new "C" class is equal to 2, the "initialize" method of class B is called but the ".Object" in the "initialize" method of class B is an object of class C. And of course in this case method dispatching chooses the "generateSpec" method of class C - "generateSpec" for class B gets never called. In general this is exactly what we want, when inheriting classes: dispatching makes OOP programming not only simpler, but actually possible. 

My question: How can I make this setting work? How can I generate an "initialize" method for class B that calls ALWAYS the "generateSpec" method of class B (using "as" lets me end up in the "initialize" method of class C with an object of class B as it is only possible to convert a derived object to its base class but not the other way around)? 

Best

Simon



More information about the R-help mailing list