From timh at insightful.com  Mon Feb 25 18:59:16 2008
From: timh at insightful.com (Tim Hesterberg)
Date: Mon, 25 Feb 2008 09:59:16 -0800
Subject: [Rd] Standard method for S4 object
In-Reply-To: <47C2F422.6040608@ebi.ac.uk> (message from Oleg Sklyar on Mon, 25
	Feb 2008 17:00:18 +0000)
References: <47C06F0A.4090505@u-paris10.fr> <uy79957by.fsf@insightful.com>
	<47C2F422.6040608@ebi.ac.uk>
Message-ID: <uve4c6hor.fsf@insightful.com>

>Tim Hesterberg wrote:
>> It depends on what the object is to be used for.
>> 
>> If you want users to be able to operate with the object as if it
>> were a normal vector, to do things like mean(x), cos(x), etc.
>> then the list would be very long indeed; for example, there are
>> 225 methods for the S4 'bdVector' class (in S-PLUS), plus additional
>> methods defined for inheriting classes.
>
>This somehow undermines the whole idea of inheritance. If you do not 
>inherit, then you are just implementing a class that mimics another one 
>from scratch. However, the question then is not about standard methods 
>any more, it's about the methods of the class that you mimic.

My experience with S4 classes is primarily with classes that had
to be implemented from scratch, there was nothing one could inherit
from - bdFrame and bdVector in library(bigdata), miVariable in
library(missing)  (sorry, these are S-PLUS only).  

Actually, for miVariable we considered S3 class + attributes, but
in this case we decided that we did NOT want operations like mean(x)
to work without going through a method specifically for the class.

>... example of "Image" class omitted here 
>
>> In cases like this you might prefer using an S3 class, using
>> attributes rather than slots for auxiliary information, so that
>> you don't need to write so many methods.
>
>The reasoning here is not really clear. Could you please explain why is 
>this better?

Three examples.  First is "bs":
> library(splines)
> bsx <- bs(1:99, knots = 10 * 2:6)
> showStructure(bsx)
numeric[99,8]  S3 class: bs basis 
 attributes: dimnames 
 &degree           scalar  class: integer 
 &knots            numeric[ length 5]  class: numeric 
 &Boundary.knots   numeric[ length 2]  class: integer 
 &intercept        logical[ length 1]  class: logical 

(I plan to add showStructure to library(splus2R) shortly.)

This is an S3 class, a matrix plus some additional attributes.
Everything that works for a matrix works for this object,
without needing additional classes.

A second example is "label":
> library(Hmisc)
>      age <- c(21,65,43)
>      label(age) <- "Age in Years"
> showStructure(age)
numeric[ length 3]  S3 class: labelled 
 &label   character[ length 1]  class: character 
> cos(age)
Age in Years 
[1] -0.5477293 -0.5624539  0.5551133

Another S3 class, basically any object plus a label attribute.
There are a few methods for this class, otherwise it works
out of the box.

The third is "lm" - a list with an S3 class.  Functions that
operate on lists work fine without extra methods.  And you can
add extra components without needing to define a new class
(I've done this in library(resample)).



[Rd] Standard method for S4 object
Tim Hesterberg