From cstrato at aon.at  Mon Apr  2 17:30:15 2007
From: cstrato at aon.at (cstrato)
Date: Mon, 02 Apr 2007 17:30:15 +0200
Subject: [Rd]  Problem with S4 inheritance: unexpected re-initialization?
Message-ID: <46112187.3090009@aon.at>

Dear S4 experts,

Since I was reminded that I posted a similar question some time ago,
I am attaching a modified version of my demo package, which allows me
to track what happens during initialization of the following similar
subclasses:
   SubSubClassA <- SubClassB <- BaseClass
   SubSubClassB <- SubClassB <- BaseClass

First, I need to create SubClassA:
 > library(myclasspkg)
 > subA <- 
new("SubClassA",filename="OutSubA",filedir="/Volumes/CoreData/CRAN/Workspaces/rclasspkg",mytitle="TitleSubA")
 
Then, I create both subclasses, SubSubClassA and SubSubClassB, either
with a virtual BaseClass or with a non-virtual BaseClass:

1. new("SubSubClassA"): BaseClass is VIRTUAL
 > subsubA <- 
new("SubSubClassA",filename="MyFileName",filedir="/Volumes/CoreData/CRAN/Workspaces/rclasspkg",subA=subA)
[1] "------initialize:SubSubClassA------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------"
[1] "------setValidity:SubClassB------"
[1] "------setValidity:SubSubClassA------"

As far as I understand the S4 classes, this is the correct initialization
workflow that I expect. The resulting object "subsubA" is correct.

However, when BaseClass is not virtual, I get the following unexpected
initialization workflow:

2. new("SubSubClassA"): BaseClass is NOT VIRTUAL
 > subsubA <- 
new("SubSubClassA",filename="MyFileName",filedir="/Volumes/CoreData/CRAN/Workspaces/rclasspkg",subA=subA)
[1] "------initialize:SubSubClassA------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------" (called but NOT executed!)
[1] "------initialize:BaseClass------" (2.initialization, why?)
[1] "------setValidity:BaseClass------"
[1] "------setValidity:SubClassB------"
[1] "------setValidity:SubSubClassA------"

The first call to setValidity is not executed, and BaseClass is
initialized twice, the second time in a completely wrong way, which
normally results in an error. Interestingly, the resulting object
"subsubA" is still correct.

The results are completely different for SubSubClassB:

3. new("SubSubClassB"): BaseClass is VIRTUAL
 > subsubB <- 
new("SubSubClassB",filename="MyFileNameB",filedir="/Volumes/CoreData/CRAN/Workspaces/rclasspkg",subA=subA)
[1] "------initialize:SubSubClassB------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"
[1] "------initialize:SubClassA------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------"
[1] "------setValidity:SubClassA------"
[1] "------setValidity:BaseClass------"
[1] "------setValidity:SubClassB------"
Error in validObject(.Object) : invalid class "SubClassB" object: 
'filename' is missing

For some unknown reason SubClassA is initialized and BaseClass is
initialized three times. SetValidity is called until an error occurs.

Things get more weird when BaseClass is not virtal:

4. new("SubSubClassB"): BaseClass is NOT VIRTUAL
 > subsubB <- 
new("SubSubClassB",filename="MyFileNameB",filedir="/Volumes/CoreData/CRAN/Workspaces/rclasspkg",subA=subA)
[1] "------initialize:SubSubClassB------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"
[1] "------initialize:SubClassA------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------"
[1] "------setValidity:SubClassA------"
[1] "------setValidity:BaseClass------"
[1] "------initialize:BaseClass------"
[1] "------setValidity:BaseClass------"
[1] "------setValidity:SubClassB------"
Error in validObject(.Object) : invalid class "SubClassB" object: 
'filename' is missing

It seems that initialization occurs in an endless cycle until an
error occurs.

Finally, let us look what happens when I follow the usual convention
where callNextMethod() is called first:

5. new("SubSubClassA"): callNextMethod() as 1.command; BaseClass is VIRTUAL
 > subsubA <- 
new("SubSubClassA",filename="MyFileName",filedir="/Volumes/CoreData/CRAN/Workspaces/rclasspkg",subA=subA)
[1] "------initialize:SubSubClassA------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"

The object "subsubA" is created correctly, however, setValidity()
is never called.

The same is true for SubSubClassB:

6. new("SubSubClassB"): callNextMethod() as 1.command; BaseClass is VIRTUAL
 > subsubB <- 
new("SubSubClassB",filename="MyFileNameB",filedir="/Volumes/CoreData/CRAN/Workspaces/rclasspkg",subA=subA)
[1] "------initialize:SubSubClassB------"
[1] "------initialize:SubClassB------"
[1] "------initialize:BaseClass------"

The object "subsubB" is for the first time created correctly, however,
once again setValidity() is never called.

Maybe, I am misunderstanding an important part of creating S4 classes.
I would be really greatful, if the S4 experts could explain me what
happens here and what might be wrong with my demo package.

As a side note, when studying the code of the S4 packages "Biobase",
"affy" and "oligo", I made the observation, that none of these packages
calls "initialize" and "setValidity" for all classes and sub-classes.

Thank you very much in advance.
Best regards
Christian

-------------- next part --------------
A non-text attachment was scrubbed...
Name: myclasspkg_0.1.1.tar.gz
Type: application/x-gzip
Size: 5523 bytes
Desc: not available
Url : https://stat.ethz.ch/pipermail/r-devel/attachments/20070402/17170514/attachment.gz 


[Rd] Problem with S4 inheritance: unexpected re-initialization?
cstrato