Rev 35751 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
\name{setOldClass}\alias{setOldClass}\alias{.setOldIs}\alias{POSIXct-class}\alias{POSIXlt-class}\alias{POSIXt-class}\alias{aov-class}\alias{maov-class}\alias{anova-class}\alias{anova.glm-class}\alias{anova.glm.null-class}\alias{data.frame-class}\alias{density-class}\alias{dump.frames-class}\alias{factor-class}\alias{formula-class}\alias{glm-class}\alias{glm.null-class}\alias{hsearch-class}\alias{integrate-class}\alias{libraryIQR-class}\alias{lm-class}\alias{logLik-class}\alias{mlm-class}\alias{mtable-class}\alias{mts-class}\alias{ordered-class}\alias{packageIQR-class}\alias{packageInfo-class}\alias{recordedplot-class}\alias{rle-class}\alias{socket-class}\alias{summary.table-class}\alias{oldClass-class}\alias{.OldClassesList}\alias{table-class}\title{ Specify Names for Old-Style Classes }\description{Register an old-style (a.k.a. `S3') class as a formally definedclass. The \code{Classes} argument is the character vector used as the\code{class} attribute; in particular, if there is more than onestring, old-style class inheritance is mimiced. Registering via\code{setOldClass} allows S3 classes to appear as slots or in methodsignatures.}\usage{setOldClass(Classes, where, test = FALSE)}\arguments{\item{Classes}{A character vector, giving the names for old-styleclasses, as they would appear on the right side of an assignment ofthe \code{class} attribute.}\item{where}{Where to store the class definitions, the global or top-levelenvironment by default. (When either function is called in thesource for a package, the class definitions will be included in thepackage's environment by default.)}\item{test}{flag, if \code{TRUE}, inheritance must be testedexplicitly for each object, needed if the S3 class can have adifferent set of class strings, with the same first string.See the details below.}}\details{Each of the names will be defined as a virtual class, extending theremaining classes in \code{Classes}, and the class\code{oldClass}, which is the \dQuote{root} of all old-style classes.See \link{Methods} for the details of method dispatch andinheritance. See the section \bold{Register or Convert?} forcomments on the alternative of defining \dQuote{real} S4 classesrather than using \code{setOldClass}.S3 classes have no formal definition, and some of them cannot berepresented as an ordinary combination of S4 classes andsuperclasses. It is still possible to register the classes as S4classes, but now the inheritance has to be verified for eachobject, and you must call \code{setOldClass} with argument\code{test=TRUE}.For example, ordered factors \emph{always} have the S3class \code{c("ordered", "factor")}. This is proper behavior, andmaps simply into two S4 classes, with \code{"ordered"} extending\code{"factor"}.But objects whose class attribute has \code{"POSIXt"} as the firststring may have either (or neither) of \code{"POSIXct"} or\code{"POSIXlt"} as the second string. This behavior can be mappedinto S4 classes but now to evaluate \code{is(x, "POSIXlt")}, forexample, requires checking the S3 class attribute on each object.Supplying the \code{test=TRUE} argument to \code{setOldClass} causesan explicit test to be included in the class definitions. It'snever wrong to have this test, but since it adds significantoverhead to methods defined for the inherited classes, you shouldonly supply this argument if it's known that object-specific testsare needed.The list \code{.OldClassesList} contains the old-style classes thatare defined by the methods package. Each element of the list is anold-style list, with multiple character strings if inheritance isincluded.Each element of the list was passed to \code{setOldClass} whencreating the \pkg{methods} package; therefore, these classes can be usedin \code{\link{setMethod}} calls, with the inheritance as implied bythe list.}\section{Register or Convert?}{A call to \code{setOldClass} creates formal classes correspondingto S3 classes, allows these to be used as slots in other classes or ina signature in \code{\link{setMethod}}, and mimics the S3 inheritance.However, all such classes are created as virtual classes, meaning thatyou cannot generally create new objects from the class by calling\code{\link{new}}, and that objects cannot be coerced automaticallyfrom or to these classes. All these restrictions just reflect thefact that nothing is inherently known about the \dQuote{structure} ofS3 classes, or whether in fact they define a consistent set ofattributes that can be mapped into slots in a formal class definition.\emph{If} your class does in fact have a consistent structure, so thatevery object from the class has the same structure, you may prefer totake some extra time to write down a specific definition in a call to\code{\link{setClass}} to convert the class to a fully functionalformal class. On the other hand, if the actual contents of the classvary from one object to another, you may have to redesign most of thesoftware using the class, in which case converting it may not be worththe effort. You should still register the class via\code{setOldClass}, unless its class attribute is hopelessly unpredictable.An S3 class has consistent structure if each object has the same setof attributes, both the names and the classes of the attributes beingthe same for every object in the class. In practice, you can convertclasses that are slightly less well behaved. If a few attributesappear in some but not all objects, you can include these optionalattributes as slots that \emph{always} appear in the objects, if youcan supply a default value that is equivalent to the attribute beingmissing. Sometimes \code{NULL} can be that value: A slot (but not anattribute) can have the value \code{NULL}. If \code{version}, forexample, was an optional attribute, the old test\code{is.null(attr(x,"version")} for a missing version attribute couldturn into \code{is.null(x@version)} for the formal class.The requirement that slots have a fixed class can be satisfiedindirectly as well. Slots \emph{can} be specified with class\code{"ANY"}, allowing an arbitrary object. However, this eliminatesan important benefit of formal class definitions; namely, automaticvalidation of objects assigned to a slot. If just a few differentclasses are possible, consider using \code{\link{setClassUnion}} todefine valid objects for a slot.}\seealso{\code{\link{setClass}}, \code{\link{setMethod}}}\examples{setOldClass(c("mlm", "lm"))setGeneric("dfResidual", function(model)standardGeneric("dfResidual"))setMethod("dfResidual", "lm", function(model)model$df.residual)## dfResidual will work on mlm objects as well as lm objectsmyData <- data.frame(time = 1:10, y = (1:10)^.5)myLm <- lm(cbind(y, y^3) ~ time, myData)\dontshow{stopifnot(identical(dfResidual(myLm), myLm$df.residual))}rm(myData, myLm)removeGeneric("dfResidual")}\keyword{ programming }\keyword{ methods }