[Rd] S3 classes in S4 class definitions
jmc at research.bell-labs.com
Wed Aug 25 22:50:36 CEST 2004
One of the changes some packages are noticing from the recent
modifications to methods is warnings of "undefined classes" during
installation when the package extends S3 classes or uses them as slots
UNLESSS they have been declared in a setOldClass() call. The green book
"strongly recommends" declaring S3 classs this way (pp 449-451).
The warnings on undeclared classes threatened in the book have now been
implemented ;-) (However the statement in the book that S3 inheritance
is not used in dispatching S4 methods is not true. Once the relevant
setOldClass call has been done, the inheritance should work.)
Since the packages using the S3 classes won't likely use any S4
methods, it will be up to new packages to include the setOldClass()
calls, unless we try to provide some more systematic bridge for the old
The text below is being added to the setClass() help file to articulate
some of the points. Comments and suggestions welcome of course.
PS: I will be away for a few days, but should be back in e-mail contact
Earlier, informal classes of objects (usually referred to as "S3"
classes) are used by many R functions. It's natural to consider
including them as the class for a slot in a formal class, or even
as a class to be extended by the new class. This isn't prohibited
but there are some disadvantages, and if you do want to include S3
classes, they should be declared by including them in a call to
'setOldClass'. Here are some considerations:
* Using S3 classes somewhat defeats the purpose of defining a
formal class: An important advantage to your users is that
a formal class provides guarantees of what the object
contains (minimally, the classes of the slots and therfore
what data they contain; optionally, any other requirements
imposed by a validity method).
But there is no guarantee whatever about the data in an
object from an S3 class. It's entirely up to the functions
that create or modify such objects. If you want to provide
guarantees to your users, you will need a valdity method
that explicitly checks the contents of S3-class objects.
* To get the minimal guarantee (that the object in a slot has,
or extends, the class for the slot) you should ensure that
the S3 classes are known to _be_ S3 classes, with the
possible inheritance. To do this, include a call to
'setOldClass' for the S3 classes used.
Otherwise, the S3 class is undefined (and the code used by
'setClass' will issue a warning). Slot assignments, for
example, will not then check for possible errors.
* These caveats apply to S3 classes; that is, objects with a
class assigned by some R function but without a formal class
definition. In contrast, the built-in data types
('numeric', 'list', etc.) are generally fine as slots or for
'contains=' classes (see the previous section). These data
types don't have formal slots, but the base code in the
system essentially forces them to contain the type of data
they claim to have.
The data types 'matrix' and 'array' are somewhat in between.
They do not have an explicit S3 class, but do have one or
two attributes. There is no general problem in having these
as slots, but because there is no guarantee of a dimnames
slot, they don't work as formal classes. The 'ts' class is
treated as a formal class, extending class 'vector'.
Plus an example of the form:
setClass("lmCommented", representation(results = "lm", comments =
aa = new("lmCommented", results = npk.aov, comments = "From the aov
try(new("lmCommented", results = npk.aovE, comments = "BAD!!"))
### causes an error because npk.aovE is of class "aovlist"
John M. Chambers jmc at bell-labs.com
Bell Labs, Lucent Technologies office: (908)582-2681
700 Mountain Avenue, Room 2C-282 fax: (908)582-3340
Murray Hill, NJ 07974 web: http://www.cs.bell-labs.com/~jmc
More information about the R-devel