From cstrato at aon.at  Sun Mar  4 19:51:45 2007
From: cstrato at aon.at (cstrato)
Date: Sun, 04 Mar 2007 19:51:45 +0100
Subject: [Rd] Problem using callNextMethod() in S4
In-Reply-To: <m2odn8apol.fsf@ziti.local>
References: <45EAF340.50707@aon.at> <m2odn8apol.fsf@ziti.local>
Message-ID: <45EB1541.2020308@aon.at>

Dear Seth

Thank you for your comments. Please see my comments and at the end my 
corrected code and output.
Sorrowly, the problem remains the same.

Seth Falcon wrote:
> cstrato <cstrato at aon.at> writes:
>
>   
>> Dear all,
>>
>> Maybe, I am doing something wrong, but using R-2.5.0 on my Intel-Mac, I 
>> have problems
>> using function callNextMethod() in method initialize.
>>
>> I am loading the following code as file "testS4.R":
>>     
>
> I don't think this is the code in the same state as that which you ran
> the examples.  Did you add/remove some comment lines perhaps?
>
> After copy/pasting the code you posted, I get:
>
>     > tmp<-new("derivedClass")
>     [1] "---initialize:derivedClass---"
>     [1] "mytitle =  MyTitle"
>     > tmp<-new("derivedClass",myname="testname",mytitle="testitle")
>     [1] "---initialize:derivedClass---"
>     [1] "mytitle =  MyTitle"
>
>   
I am sorry, you are correct, I have commented out ".Object <- 
callNextMethod()" in method
initialize for derivedClass afterwards.
>> setValidity("baseClass",
>>    function(object) {
>> print("---setValidity:baseClass---")
>>       strg <- object at myname;
>>       if (!(is(strg, "character") && nchar(strg) > 0)) {
>>          warning(paste(sQuote("myname"), "is missing"));
>>       }#if
>> print(paste("myname = ",object at myname))
>>       strg <- object at mydir;
>>       if (!(is(strg, "character") && file.exists(strg))) {
>>          warning(paste(sQuote("mydir"), "is not a system directory"));
>>       }#if
>>       if (substr(strg, nchar(strg), nchar(strg)) == "/") {
>>          object at mydir <- substr(strg, 0, nchar(strg)-1);
>>       }#if
>> print(paste("mydir = ",object at mydir))
>>    }
>> )#setValidity
>>     
>
> Your validity function isn't valid :-P It should either return TRUE or
> return a character vector describing what isn't valid about the
> object.  Don't call warning() or print().
>   
Please see my corrected code where I use "validMsg()" from BioBase.
> Also, you don't need those ';'
>
> And finally, you are operating on a _copy_ in the validity method
> (just like everywhere else) and so this
>
>   
>>       if (substr(strg, nchar(strg), nchar(strg)) == "/") {
>>          object at mydir <- substr(strg, 0, nchar(strg)-1);
>>       }#if
>>     
>
> will not have any effect on the instance passed in.  It is an odd
> thing to do in a validity method.
>   
You are right, I moved this code to method "initialize".
> + seth
>
>   
Here is my new code "testS4.R" (as used in the output):

setClass("baseClass",
   representation(myname = "character",
                  mydir  = "character",
                  "VIRTUAL"),
   prototype(myname = "",
             mydir  = "")
)#baseClass

setClass("derivedClass",
   representation(mytitle = "character"),
   contains=c("baseClass"),
   prototype(mytitle = "")
)#derivedClass

# taken from package BioBase: tools.R
validMsg <- function(msg, result) {
   if (is.character(result)) {
      append(msg, result);
   } else {
      msg;
   }#if
}

setMethod("initialize", "baseClass",
   function(.Object, ...) {
print("---initialize:baseClass---")
#    .Object <- callNextMethod();
      strg <- .Object at mydir;
print(paste("base:strg = ", strg))
      if (strg == "") {
         .Object at mydir <- as.character(getwd());
      }#if
      if (substr(strg, nchar(strg), nchar(strg)) == "/") {
         .Object at mydir <- substr(strg, 0, nchar(strg)-1);
      }#if
print(paste("base:mydir = ", .Object at mydir))
    .Object <- callNextMethod();
    .Object;
   }
)#initialize

setValidity("baseClass",
   function(object) {
print("---setValidity:baseClass---")
      msg <- NULL;
      strg <- object at myname;
      if (!(is(strg, "character") && nchar(strg) > 0)) {
         msg <- validMsg(msg, paste(sQuote("myname"), "is missing"));
      }#if
print(paste("base:myname = ",object at myname))
      strg <- object at mydir;
      if (!(is(strg, "character") && file.exists(strg))) {
         msg <- validMsg(msg, paste(sQuote("mydir"), "is not a system 
directory"));
      }#if
print(paste("base:mydir = ",object at mydir))
      if (is.null(msg)) TRUE else msg;
   }
)#setValidity

setMethod("initialize", "derivedClass",
   function(.Object, ...) {
print("---initialize:derivedClass---")
#    .Object <- callNextMethod();
      if (.Object at mytitle == "") {
         .Object at mytitle = "MyTitle";
      }#if
print(paste("derived:mytitle = ",.Object at mytitle))
    .Object <- callNextMethod();
    .Object;
   }
)#initialize

setValidity("derivedClass",
   function(object) {
print("---setValidity:derivedClass---")
      msg <- NULL;
      strg <- object at mytitle;
      if (!(is(strg, "character") && nchar(strg) > 0)) {
         msg <- validMsg(msg, paste(sQuote("mytitle"), "is missing"));
      }#if
print(paste("derived:mytitle = ",object at mytitle))
      if (is.null(msg)) TRUE else msg;
   }
)#setValidity


Here is the new output with the same error:

 > library(methods)
 > source("testS4.R")
 > tmp<-new("derivedClass")
[1] "---initialize:derivedClass---"
[1] "derived:mytitle =  MyTitle"
[1] "---initialize:baseClass---"
[1] "base:strg =  "
[1] "base:mydir =  /Volumes/CoreData/CRAN/Workspaces/tests"
 >
 > tmp<-new("derivedClass",myname="testname",mydir="",mytitle="testitle")
[1] "---initialize:derivedClass---"
[1] "derived:mytitle =  MyTitle"
[1] "---initialize:baseClass---"
[1] "base:strg =  "
[1] "base:mydir =  /Volumes/CoreData/CRAN/Workspaces/tests"
[1] "---setValidity:baseClass---"
[1] "base:myname =  testname"
[1] "base:mydir =  "
Error in validObject(.Object) : invalid class "derivedClass" object: 
'mydir' is not a system directory

I do not understand why "mydir" is not recognized correctly?

Thank you
Christian



[Rd] Problem using callNextMethod() in S4
cstrato