blob: bd918b50657abdfd9378846d6be3c89b24fa67ff [file] [log] [blame]
% File src/library/methods/man/setOldClass.Rd
% Part of the R package, https://www.R-project.org
% Copyright 1995-2010, 2016 R Core 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{Date-class}
\alias{data.frame-class}
\alias{data.frameRowLabels-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{summaryDefault-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{Register Old-Style (S3) Classes and Inheritance}
\description{
Register an old-style (a.k.a. \sQuote{S3}) class as a formally defined
class. Simple usage will be of the form:
\code{setOldClass(Classes)}
where \code{Classes} is the character vector that would be the
\code{class} attribute of the S3 object. Calls to
\code{setOldClass()} in the code for a package
allow the class to be used as a slot in formal (S4) classes and in
signatures for methods (see \link{Methods_for_S3}).
Formal classes can also contain a registered S3 class (see
\link{S3Part} for details).
If the S3 class has a known set of attributes, an
equivalent S4 class can be specified by \code{S4Class=} in the call to
\code{setOldClass()}; see the section \dQuote{Known Attributes}.
}
\usage{
setOldClass(Classes, prototype, where, test = FALSE, S4Class)
}
\arguments{
\item{Classes}{
A character vector, giving the names for S3
classes, as they would appear on the right side of an assignment of
the \code{class} attribute in S3 computations.
In addition to S3 classes, an object type or other valid data part
can be specified, if the S3 class is known to require its data to
be of that form.
}
\item{S4Class}{ optionally, the class definition or the class name
of an S4 class. The new class will have all the slots and other
properties of this class, plus any S3 inheritance implied by
multiple names in the \code{Classes} argument. See the section
on \dQuote{S3 classes with known attributes} below.
}
\item{prototype, where, test}{\emph{These arguments are currently
allowed, but not recommended in typical applications.}
\code{prototype}:
An optional object to use as the prototype. If the S3 class is
not to be \code{VIRTUAL} (the default), the use of \code{S4Class=} is
preferred.
\code{where}:
Where to store the class definitions. Should be the default (the
package namespace) for normal use in an application package.
\code{test}: flag, if \code{TRUE}, arrange to test inheritance
explicitly for each object, needed if the S3 class can have a
different set of class strings, with the same first string.
Such classes are inherently malformed, are rare, and should be avoided.
}
}
\details{
The name (or each of the names) in \code{Classes} will be defined as an S4 class, extending class \code{oldClass},
which is the \sQuote{root} of all old-style classes. S3 classes
with multiple names in their class attribute will have a
corresponding inheritance as formal classes. See the \code{"mlm"} example.
S3 classes have
no formal definition, and therefore no formally defined slots.
If no S4 class is supplied as a model, the class created will be a
virtual class.
If a virtual class (any virtual class) is used for a slot in another class, then the
initializing method for the class needs to put something legal in
that slot; otherwise it will be set to \code{NULL}.
See \link{Methods_for_S3} for the details of method dispatch and
inheritance with mixed S3 and S4 methods.
Some S3 classes cannot be represented as an ordinary combination of S4
classes and superclasses, because objects with the same initial
string in the class attribute can have different strings following.
Such classes are fortunately rare. They violate the basic idea of
object-oriented programming and should be avoided.
If you must deal with them, it is still possible to register
such classes as S4 classes, but now the inheritance has to be verified
for each object, and you must call \code{setOldClass} with argument
\code{test=TRUE}.
}
\section{Pre-Defined Old Classes}{
Many of the widely used S3 classes in the standard R distribution
come pre-defined for use with S4. These don't need to be explicitly
declared in your package (although it does no harm to do so).
The list \code{.OldClassesList} contains the old-style classes that
are defined by the methods package. Each element of the list is a
character vector, with multiple strings if inheritance is included.
Each element of the list was passed to \code{setOldClass} when
creating the \pkg{methods} package; therefore, these classes can be used
in \code{\link{setMethod}} calls, with the inheritance as implied by
the list.
}
\section{S3 Classes with known attributes}{
A further specification of an S3 class can be made \emph{if} the
class is guaranteed to have some attributes of known class (where as
with slots, \dQuote{known} means that the attribute is an object of
a specified class, or a subclass of that class).
In this case, the call to \code{setOldClass()} can supply an S4 class
definition representing the known structure. Since S4 slots are
implemented as attributes (largely for just this reason), the known
attributes can be specified in the representation of the S4 class.
The usual technique will be to create an S4 class with the desired
structure, and then supply the class name or definition as the
argument \code{S4Class=} to \code{setOldClass()}.
See the definition of class \code{"ts"} in the examples below and
the \code{data.frame} example in Section 10.2 of the reference.
The call to \code{\link{setClass}} to create the S4 class can use the same
class name, as here, so long as the call to \code{setOldClass}
follows in the same package. For clarity it should be the next
expression in the same file.
In the example, we define \code{"ts"} as a vector structure with a
numeric slot for \code{"tsp"}. The validity of this definition relies
on an assertion that all the S3 code for this class is consistent with
that definition; specifically, that all \code{"ts"} objects will
behave as vector structures and will have a numeric \code{"tsp"}
attribute. We believe this to be true of all the base code in \R, but
as always with S3 classes, no guarantee is possible.
The S4 class definition can have virtual superclasses (as in
the \code{"ts"} case) if the S3 class is asserted to behave
consistently with these (in the example, time-series objects are
asserted to be consistent with the \linkS4class{structure} class).
Failures of the S3 class to live up to its asserted
behavior will usually go uncorrected, since S3 classes inherently
have no definition, and the resulting invalid S4 objects can cause
all sorts of grief. Many S3 classes are not candidates for known
slots, either because the presence or class of the attributes are
not guaranteed (e.g., \code{dimnames} in arrays, although these are
not even S3 classes), or because the class uses named components of
a list rather than attributes (e.g., \code{"lm"}). An attribute
that is sometimes missing cannot be represented as a slot, not even
by pretending that it is present with class \code{"NULL"}, because
attributes, unlike slots, can not have value \code{NULL}.
One irregularity that is usually tolerated, however, is to optionally
add other attributes to those guaranteed to exist (for example,
\code{"terms"} in \code{"data.frame"} objects returned by
\code{\link{model.frame}}). Validity checks by
\code{\link{validObject}} ignore extra attributes; even if this check
is tightened in the future, classes extending S3 classes would likely
be exempted because extra attributes are so common.
}
\seealso{
\code{\link{setClass}}, \code{\link{setMethod}}
}
\references{
Chambers, John M. (2016)
\emph{Extending R},
Chapman & Hall.
(Chapters 9 and 10, particularly Section 10.8)
}
\examples{
\dontshow{
## All the predefined S3 classes with S4 versions
sort(unlist(.OldClassesList))
}
require(stats)
## "lm" and "mlm" are predefined; if they were not this would do it:
\dontrun{
setOldClass(c("mlm", "lm"))}
## Define a new generic function to compute the residual degrees of freedom
setGeneric("dfResidual",
function(model) stop(gettextf(
"This function only works for fitted model objects, not class \%s",
class(model))))
setMethod("dfResidual", "lm", function(model)model$df.residual)
## dfResidual will work on mlm objects as well as lm objects
myData <- data.frame(time = 1:10, y = (1:10)^.5)
myLm <- lm(cbind(y, y^3) ~ time, myData)
\dontshow{
showClass("data.frame")# to see the predefined S4 "oldClass"
}
## two examples extending S3 class "lm": class "xlm" directly
## and "ylm" indirectly
setClass("xlm", slots = c(eps = "numeric"), contains = "lm")
setClass("ylm", slots = c(header = "character"), contains = "xlm")
ym1 = new("ylm", myLm, header = "Example", eps = 0.)
## for more examples, see ?\link{S3Class}.
\dontshow{
stopifnot(identical(dfResidual(myLm), myLm$df.residual))
removeClass("ylm"); removeClass("xlm")
rm(myData, myLm)
removeGeneric("dfResidual")}
\dontrun{
## The code in R that defines "ts" as an S4 class
setClass("ts", contains = "structure", slots = c(tsp = "numeric"),
prototype(NA, tsp = rep(1,3)))
# prototype to be a legal S3 time-series
## and now registers it as an S3 class
setOldClass("ts", S4Class = "ts", where = envir)
}
}
\keyword{ programming }
\keyword{ methods }