Rev 42963 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
% File src/library/methods/man/setOldClass.Rd% Part of the R package, http://www.R-project.org% Copyright 1995-2007 R Core Development Team% Distributed under GPL 2 or later\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}\alias{initialize,data.frame-method}\alias{initialize,factor-method}\alias{initialize,ordered-method}\alias{initialize,table-method}\alias{initialize,summary.table-method}\title{ Specify Names for Old-Style Classes }\description{Register an old-style (a.k.a. \sQuote{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 mimicked. Registering via\code{setOldClass} allows S3 classes to appear in methodsignatures, and as a slot in an S4 class if a prototype is included.}\usage{setOldClass(Classes, prototype, 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{prototype}{An optional object to use as the prototype. This should be providedas the default S3 object for the class, if you plan to use the class asa slot in an S4 class. See the details section.}\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 an S4 class, extending theremaining classes in \code{Classes}, and the class \code{oldClass},which is the \sQuote{root} of all old-style classes. S3 classes haveno formal definition, and therefore no formally defined slots. If a\code{prototype} argument is supplied in the call to\code{setOldClass()}, objects from the class can be generated. If theS3 class is to be a slot in an S4 class, providing a prototype isrecommended. Otherwise, the class will be created as a virtual S4class; method dispatch will still work and inheritance will follow theS3 class hierarchy, but actions that require a prototype object fromthe class will not. For example, using the class as a slot in an S4class definition will set the corresponding slot to \code{NULL} in theprototype for the S4 class.Providing a prototype allows the function \code{new()} to be calledfor this class, but optional arguments in this call are notmeaningful, since the class has no formal slots. Extending an S3 classwith an S4 class is formally legal, but discouraged. Since the S4subclass will have a single character string in its \code{class()}, S3inheritance will not work. Also, there is no safe way for a generalobject from the S3 class to be inserted when an object is generatedfrom the subclass.See \link{Methods} for the details of method dispatch andinheritance. See the section \bold{Register or Convert?} forcomments on the alternative of defining \sQuote{real} S4 classesrather than using \code{setOldClass}.Some S3 classes cannot be represented as an ordinary combination of S4classes and superclasses, because objects from the S3 class can have avariable set of strings in the class. It is still possible to registersuch classes as S4 classes, but now the inheritance has to be verifiedfor each object, and you must call \code{setOldClass} with argument\code{test=TRUE} once for each superclass.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.Supplying the \code{prototype} and optionally the \code{generator} arguments allows the S4 class created to be non-virtual, making it a candidate to be a slot in S4 class definitions and to be extended by S4 classes.The class still does not have formally defined slots.Because R implements slots as attributes, an S3 class that uses attributes (\code{factor}, for example) can in principle be defined as an S4 class with slots.However, a class such as \code{lm} that uses components of a list in a similar role cannot have formal slots.The slots would not be interpreted by S3 code written for \code{lm} objects.\emph{If} your class does in fact have a consistent set of attributes, 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, such a definition will not generally be possible. 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{\dontshow{## VOODO Why is this needed?removeMethods("length")}require(stats)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")\dontrun{setOldClass("data.frame", prototoype = data.frame())}}\keyword{ programming }\keyword{ methods }