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 code. The text below is being added to the setClass() help file to articulate some of the points. Comments and suggestions welcome of course. John PS: I will be away for a few days, but should be back in e-mail contact on Monday. -------------------------- \section{S3 Classes} 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: setOldClass(c("aov", "lm")) setClass("lmCommented", representation(results = "lm", comments "character")) aa = new("lmCommented", results = npk.aov, comments = "From the aov example") try(new("lmCommented", results = npk.aovE, comments = "BAD!!")) ### causes an error because npk.aovE is of class "aovlist" -- John M. Chambers jmc@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