From jmc at r-project.org  Fri Sep 15 15:46:42 2006
From: jmc at r-project.org (John Chambers)
Date: Fri, 15 Sep 2006 09:46:42 -0400
Subject: [Rd] attributes of S4 objects
In-Reply-To: <B1EBE009-6321-40D6-B427-BAF7BEE415D3@mac.com>
References: <B1EBE009-6321-40D6-B427-BAF7BEE415D3@mac.com>
Message-ID: <450AAEC2.7060103@r-project.org>

Parlamis Franklin wrote:
> I am having a bit of a struggle deciding when to use attributes with  
> S4 objects.  Clearly the 'class' attribute will always be present.   
> But it is not clear to me whether the architects of the methods  
> package intend that other attributes, such as 'names', will still be  
> used when the S4 implementation is complete.
>   
"Can of worms" might be a good description of this situation.

The cautious approach would be to not assume attributes get carried over 
to an object that uses a basic R data type ("numeric" in your example) 
as the data in the new class.  If you need arbitrary attributes, it's 
safer to make the old-style object into a slot:
  setClass("Numeric", representation(x = "numeric"))
which should not balk at the slot having attributes.

Here's the underlying point:  There are two very different computing 
models here.  Old-style attributes were basically undisciplined; each 
object could have its own collection of attributes and these could 
appear and disappear.  Names are a good example:

 > z = 1:10
 > names(z) <- letters[1:10]
 > names(attributes(z))
[1] "names"
 > names(z) <- NULL
 > names(attributes(z))
NULL

In contrast, S4 class definitions guarantee what slots are available, 
and that they inherit from specified classes.  So if names() in the S3 
sense were made a part of the S4 object, they could not just disappear 
as in this example.  But then it's doubtful that the great mound of code 
that uses names in the S3 sense would still all work correctly for 
objects from the S4 classes.  So the safe approach is to keep the two 
ideas separate.

There are many ways to bridge the gap; for example, by having an 
initialize() method for the S4 class that takes attributes from an S3 
object and copies them into slots in the S4 object, when the attributes 
happen to be there.


> I notice that, when you create a formal object from an informal one  
> with attributes, the attributes are (often) assigned to the formal  
> object.  For example,
>
> setClass("Numeric", representation("numeric"))
> vec <- 1:10
> names(vec) <- letters[1:10]
> comment(vec) <- "comment"
> Vec <- new("Numeric", vec)
> attributes(Vec) ## 'names' and 'comment' attributes are assigned to  
> the formal object
>
> But I also notice that, in the absence of an appropriate 'coerce'  
> method, 'as(   , superclass)' will return an object without attributes
>
> as(Vec, "numeric") ## gives an unnamed vector of mode numeric with no  
> comment attribute
>
> Because of this, I have found myself writing methods for the sole  
> purpose of preserving attributes when coercing between basic data  
> types and formal classes that extend them.  But the default methods  
> for coercing to the basic data types clearly want attributes to be  
> stripped (they do so explicitly when strict=TRUE (the default)).  I  
> am thinking that maybe it was always intended that non-class  
> attributes would not be used with formal objects, and that instead  
> analogous slots would appear in any formal objects that extend basic  
> data types (like the Dim and Dimnames attributes in the 'Matrix'  
> mother class from the Matrix package).
>
> Is that true?  Are attributes un-S4?  Any and all style advice or  
> examples would be appreciated.
>
> Franklin Parlamis
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>




[Rd] attributes of S4 objects
John Chambers