Skip to content
Prev 316892 / 398503 Next

S4 Classes and Initialize methods

On 02/05/2013 04:42 AM, Franck Doray wrote:
Hi Franck --

That's probably not a useful question to ask, it's an implementation detail, but 
I think because S4 classes have a prototype, and the default prototype for class 
B's slot 'a' is constructed by calling new("A"):

 > getClassDef("B")@prototype
<S4 Type Object>
attr(,"a")
An object of class "A"
Slot "a":
numeric(0)

attr(,"b")
numeric(0)

Maybe you came across this issue in some context? A couple of thoughts...

 >> setMethod("initialize","A",function(.Object){cat("*** initialize A
 > ***\n");return(.Object)})
 > [1] "initialize"

Usually one wants to add '...' to the initialize method, and to callNextMethod() 
inside initialize. This is because the default method fills in slots with named 
arguments, so derived (perhaps even 'A') classes with simple slot initialization 
do not need an initialize method at all. Thus

setMethod(initialize, "A", function(.Object, ...) {
     message("initialize,A-method")
     callNextMethod(.Object, ...)
})

C = setClass("C", contains="A", representation=representation(x="numeric"))
C(a=1:5, x=5:1)

with

 > C(a=1:5, x=5:1)
initialize,A-method
An object of class "C"
Slot "x":
[1] 5 4 3 2 1

Slot "a":
[1] 1 2 3 4 5

(this uses a feature added in a relatively recent R, where setClass returns a 
constructor which is basically a call to 'new').

 > C
class generator function for class "C" from package '.GlobalEnv'
function (...)
new("C", ...)

Since my initialize,A-method doesn't actually do anything useful, I would 
normally not implement it. If I were to write an initialize method, e.g,. 
coercing 'x' to their absolute value, I'd write it so that (a) there is a 
default value to 'x', so that new("A") with no arguments works and (b) make sure 
that the argument 'x' came after ..., so that unnamed arguments are used in the 
initialize method's copy construction mode. I try to illustrate this below

A <- setClass("A",representation=representation(a="numeric"))
setMethod(initialize, "A", function(.Object, ..., a=numeric()) {
     callNextMethod(.Object, ..., a=abs(a))
})

And then

 > ## no-arg constructor
 > A()
An object of class "A"
Slot "a":
numeric(0)

 > ## constructor with arg
 > (a1 = A(a=-(1:5)))
An object of class "A"
Slot "a":
[1] 1 2 3 4 5

 > ## copy constructor
 > initialize(a1, a=-(5:1))
An object of class "A"
Slot "a":
[1] 5 4 3 2 1

The above is with

 > R.version.string
[1] "R Under development (unstable) (2013-02-02 r61819)"

Martin