The R Project SVN R

Rev

Rev 59039 | Rev 71228 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
42333 ripley 1
% File src/library/methods/man/setOldClass.Rd
2
% Part of the R package, http://www.R-project.org
59039 ripley 3
% Copyright 1995-2010 R Core Team
42333 ripley 4
% Distributed under GPL 2 or later
5
 
21070 jmc 6
\name{setOldClass}
56186 murdoch 7
\alias{setOldClass}
25816 jmc 8
\alias{.setOldIs}
21345 jmc 9
\alias{POSIXct-class}
25816 jmc 10
\alias{POSIXlt-class}
21345 jmc 11
\alias{POSIXt-class}
25816 jmc 12
\alias{aov-class}
13
\alias{maov-class}
21345 jmc 14
\alias{anova-class}
15
\alias{anova.glm-class}
16
\alias{anova.glm.null-class}
46128 jmc 17
\alias{Date-class}
21345 jmc 18
\alias{data.frame-class}
46503 jmc 19
\alias{data.frameRowLabels-class}
21345 jmc 20
\alias{density-class}
21
\alias{dump.frames-class}
22
\alias{factor-class}
23
\alias{formula-class}
24
\alias{glm-class}
25
\alias{glm.null-class}
26
\alias{hsearch-class}
27
\alias{integrate-class}
28
\alias{libraryIQR-class}
29
\alias{lm-class}
30
\alias{logLik-class}
31
\alias{mlm-class}
32
\alias{mtable-class}
33
\alias{mts-class}
34
\alias{ordered-class}
35
\alias{packageIQR-class}
36
\alias{packageInfo-class}
37
\alias{recordedplot-class}
38
\alias{rle-class}
39
\alias{socket-class}
51997 ripley 40
\alias{summaryDefault-class}
21345 jmc 41
\alias{summary.table-class}
42
\alias{oldClass-class}
43
\alias{.OldClassesList}
44
\alias{table-class}
37403 jmc 45
\alias{initialize,data.frame-method}
46
\alias{initialize,factor-method}
47
\alias{initialize,ordered-method}
48
\alias{initialize,table-method}
49
\alias{initialize,summary.table-method}
51997 ripley 50
\title{Register Old-Style (S3) Classes and Inheritance}
21070 jmc 51
\description{
42761 ripley 52
  Register an old-style (a.k.a. \sQuote{S3}) class as a formally defined
30666 ripley 53
  class. The \code{Classes} argument is the character vector used as the
54
  \code{class} attribute; in particular, if there is more than one
51997 ripley 55
  string, old-style class inheritance is mimicked.  Registering via
56
  \code{setOldClass} allows S3 classes to appear in method signatures,
57
  as a slot in an S4 class, or as a superclass of an S4 class.
21070 jmc 58
}
59
\usage{
46503 jmc 60
setOldClass(Classes, prototype, where, test = FALSE, S4Class)
21070 jmc 61
}
62
\arguments{
30666 ripley 63
  \item{Classes}{
49770 jmc 64
    A character vector, giving the names for S3
30666 ripley 65
    classes, as they would appear on the right side of an assignment of
46128 jmc 66
    the \code{class} attribute in S3 computations.
49770 jmc 67
 
68
    In addition to S3 classes, an object type or other valid data part
69
    can be specified, if the S3 class is known to require its data to
70
    be of that form.
30666 ripley 71
  }
37403 jmc 72
\item{prototype}{
41508 ripley 73
    An optional object to use as the prototype.  This should be provided
46128 jmc 74
    as the default S3 object for the class.  If omitted, the S4 class
75
    created to register the S3 class is \code{VIRTUAL}.  See the
76
    details.
37403 jmc 77
  }
30666 ripley 78
  \item{where}{
79
    Where to store the class definitions, the global or top-level
80
    environment by default.  (When either function is called in the
81
    source for a package, the class definitions will be included in the
82
    package's environment by default.)
83
  }
51213 maechler 84
  \item{test}{flag, if \code{TRUE}, arrange to test inheritance
30666 ripley 85
    explicitly for each object, needed if the S3 class can have a
86
    different set of class strings, with the same first string.
46503 jmc 87
    This is a different mechanism in implementation and should be
88
    specified separately for each pair of classes that have an
51997 ripley 89
    optional inheritance.  See the \sQuote{Details}.
30666 ripley 90
  }
46503 jmc 91
  \item{S4Class}{ optionally, the class definition or the class name
51997 ripley 92
    of an S4 class.  The new class will have all the slots and other
93
    properties of this class, plus its S3 inheritance as defined by
94
    the \code{Classses} argument.  Arguments \code{prototype} and
95
    \code{test} must not be supplied in this case.  See the section
96
    on \dQuote{S3 classes with known attributes} below.
46503 jmc 97
  }
51997 ripley 98
}
21070 jmc 99
\details{
37403 jmc 100
  Each of the names will be defined as an S4 class, extending the
42963 ripley 101
  remaining classes in \code{Classes}, and the class \code{oldClass},
102
  which is the \sQuote{root} of all old-style classes. S3 classes have
103
  no formal definition, and therefore no formally defined slots. If a
104
  \code{prototype} argument is supplied in the call to
46128 jmc 105
  \code{setOldClass()}, objects from the class can be generated, by a
106
  call to \code{\link{new}}; however, this usually not as relevant as
107
  generating objects from subclasses (see the section on extending S3
108
  classes below).   If  a prototype is not provided,
51997 ripley 109
   the class will be created as a virtual S4 class.
110
  The main disadvantage is that the prototype object in an S4 class that
111
  uses this class as a slot will have a \code{NULL} object in that slot,
112
  which can sometimes lead to confusion.
37403 jmc 113
 
51997 ripley 114
  Beginning with version 2.8.0 of \R, support is provided for using a
115
  (registered) S3 class as a superclass of a new S4 class.  See the
116
  section on extending S3 classes below, and the examples.
37403 jmc 117
 
25816 jmc 118
  See \link{Methods} for the details of method dispatch and
46128 jmc 119
  inheritance.
21345 jmc 120
 
42963 ripley 121
  Some S3 classes cannot be represented as an ordinary combination of S4
122
  classes and superclasses, because objects from the S3 class can have a
123
  variable set of strings in the class. It is still possible to register
124
  such classes as S4 classes, but now the inheritance has to be verified
125
  for each object, and you must call \code{setOldClass} with argument
37403 jmc 126
  \code{test=TRUE} once for each superclass.
25816 jmc 127
 
128
  For example, ordered factors \emph{always} have the S3
129
  class \code{c("ordered", "factor")}.  This is proper behavior, and
130
  maps simply into two S4 classes, with \code{"ordered"} extending
131
  \code{"factor"}.
132
 
133
  But objects whose class attribute has \code{"POSIXt"} as the first
134
  string may have either (or neither) of \code{"POSIXct"} or
135
  \code{"POSIXlt"} as the second string.  This behavior can be mapped
136
  into S4 classes but now to evaluate \code{is(x, "POSIXlt")}, for
137
  example, requires checking the S3 class attribute on each object.
138
  Supplying the \code{test=TRUE} argument to \code{setOldClass} causes
139
  an explicit test to be included in the class definitions.  It's
140
  never wrong to have this test, but since it adds significant
141
  overhead to methods defined for the inherited classes, you should
142
  only supply this argument if it's known that object-specific tests
143
  are needed.
144
 
30666 ripley 145
  The list \code{.OldClassesList} contains the old-style classes that
51213 maechler 146
  are defined by the methods package.  Each element of the list is a
147
  character vector, with multiple strings if inheritance is included.
21345 jmc 148
  Each element of the list was passed to \code{setOldClass} when
25118 hornik 149
  creating the \pkg{methods} package; therefore, these classes can be used
23678 jmc 150
  in \code{\link{setMethod}} calls, with the inheritance as implied by
151
  the list.
21070 jmc 152
}
153
 
46503 jmc 154
\section{Extending S3 classes}{
30666 ripley 155
  A call to \code{setOldClass} creates formal classes corresponding
156
  to S3 classes, allows these to be used as slots in other classes or in
46128 jmc 157
  a signature in \code{\link{setMethod}}, and mimics the S3
158
  inheritance.
25816 jmc 159
 
46128 jmc 160
  In documentation for the initial implementation of S4 classes in \R,
161
  users were warned against defining S4 classes that contained S3
162
  classes, even if those had been registered.  The warning was based
46503 jmc 163
  mainly on two points.  1: The S3 behavior of the objects would fail
46128 jmc 164
  because the S3 class would not be visible, for example, when S3
46503 jmc 165
  methods are dispatched.  2: Because S3 classes have no formal
46128 jmc 166
  definition, nothing can be asserted in general about the S3 part of
167
  an object from such a class.  (The warning was repeated as recently
168
  as the first reference below.)
25816 jmc 169
 
46128 jmc 170
  Nevertheless, defining S4 classes to contain an S3 class and extend
171
  its behavior is attractive in many applications.  The alternative is
172
  to be stuck with S3 programming, without the flexibility and security of
173
  formal class and method definitions.
25816 jmc 174
 
46503 jmc 175
  Beginning with version 2.8.0, \R provides support for extending
46128 jmc 176
  registered S3 classes; that is, for new classes defined by a call to
177
  \code{\link{setClass}} in which the \code{contains=} argument
178
  includes an S3 class.  See the examples below.  The support is aimed
179
  primarily at providing the S3 class information for all classes that
180
  extend class \linkS4class{oldClass}, in particular by ensuring that
46503 jmc 181
  all objects from such classes contain the S3 class in a special
182
  slot.
25816 jmc 183
 
51997 ripley 184
  There are three different ways to indicate an extension to an existing
185
  S3 class:  \code{setOldClass()},  \code{setClass()} and
186
  \code{setIs()}.  In most cases, calling \code{setOldClass} is the
187
  best approach,  but the alternatives may be preferred in the special
188
  circumstances described below.
46531 jmc 189
 
51997 ripley 190
  Suppose \code{"A"} is any class extending \code{"oldClass"}. then
46531 jmc 191
 
51997 ripley 192
  \code{setOldClass(c("B", "A"))}
46531 jmc 193
 
51997 ripley 194
  creates a new class \code{"B"} whose S3 class
195
  concatenates \code{"B"}  with \code{S3Class("A")}.  The new class is a
196
  virtual class.  If \code{"A"} was defined with known attribute/slots,
197
  then \code{"B"} has these slots also; therefore, you must believe that
198
  the corresponding S3 objects from class \code{"B"} do indeed have the
199
  claimed attributes.  Notice that you can supply an S4 definition for the
200
  new class to specify additional attributes (as described in the next
201
  section.)
202
  The first alternative call produces a non-virtual class.
46531 jmc 203
 
51997 ripley 204
  \code{setClass("B", contains = "A")}
46531 jmc 205
 
51997 ripley 206
  This creates a non-virtual class with the same slots and superclasses
207
  as class \code{"A"}.  However, class \code{"B"} is not included in
208
  the S3 class slot of the new class, unless you provide it explicitly
209
  in the prototype.
46531 jmc 210
 
51997 ripley 211
  \code{setClass("B"); setIs("B", "A", .....)}
46531 jmc 212
 
51997 ripley 213
  This creates a virtual class that extends \code{"A"}, but does not
214
  contain the slots of \code{"A"}.  The additional arguments to
215
  \code{\link{setIs}} should provide a coerce and replacement method.
216
  In order for the new class to inherit S3 methods, the coerce method must
217
  ensure that the class \code{"A"} object produced has a suitable S3
218
  class.  The only likely reason to prefer this third approach is that
219
  class \code{"B"} is not consistent with known attributes in class
220
  \code{"A"}.
46531 jmc 221
 
51997 ripley 222
  Beginning with version 2.9.0 of \R, objects from a class extending an
223
  S3 class will be converted to the corresponding S3 class when being
224
  passed to an S3 method defined for that class (that is, for one of the
225
  strings in the S3 class attribute).  This is intended to ensure, as
226
  far as possible, that such methods will work if they work for ordinary
227
  S3 objects.  See \code{\link{Classes}} for details.
228
}
48062 jmc 229
 
46503 jmc 230
\section{S3 Classes with known attributes}{
231
  A further specification of an S3 class can be made \emph{if} the
232
  class is guaranteed to have some attributes of known class (where as
233
  with slots, \dQuote{known} means that the attribute is an object of
234
  a specified class, or a subclass of that class).
235
 
236
  In this case, the call to \code{setOldClass()} can supply an S4 class
237
  definition representing the known structure.  Since S4 slots are
238
  implemented as attributes (largely for just this reason), the know
239
  attributes can be specified in the representation of the S4 class.
240
  The usual technique will be to create an S4 class with the desired
241
  structure, and then supply the class name or definition as the
51213 maechler 242
  argument \code{S4Class} to \code{setOldClass()}.
46503 jmc 243
 
244
  See the definition of class \code{"ts"} in the examples below.  The
51997 ripley 245
  call to \code{\link{setClass}} to create the S4 class can use the same
246
  class name, as here, so long as the class definition is not sealed.
247
  In the example, we define \code{"ts"} as a vector structure with a
248
  numeric slot for \code{"tsp"}.  The validity of this definition relies
249
  on an assertion that all the S3 code for this class is consistent with
46503 jmc 250
  that definition; specifically, that all \code{"ts"} objects will
251
  behave as vector structures and will have a numeric \code{"tsp"}
51997 ripley 252
  attribute. We believe this to be true of all the base code in \R, but
253
  as always with S3 classes, no guarantee is possible.
46503 jmc 254
 
255
  The S4 class definition can  have virtual superclasses (as in
256
  the \code{"ts"} case) if the S3 class is asserted to behave
257
  consistently with these (in the example, time-series objects are
258
  asserted to be consistent with the \linkS4class{structure} class).
259
 
51997 ripley 260
  For another example, look at the S4 class definition for \code{"data.frame"}.
46503 jmc 261
 
262
  Be warned that failures of the S3 class to live up to its asserted
263
  behavior will usually go uncorrected, since S3 classes inherently
264
  have no definition, and the resulting invalid S4 objects can cause
265
  all sorts of grief.  Many S3 classes are not candidates for known
266
  slots, either because the presence or class of the attributes are
267
  not guaranteed  (e.g., \code{dimnames} in arrays, although these are
268
  not even S3 classes), or because the class uses named components of
269
  a list rather than attributes (e.g., \code{"lm"}).  An attribute
270
  that is sometimes missing cannot be represented as a slot, not even
271
  by pretending that it is present with class \code{"NULL"}, because
272
  attributes unlike slots can not have value \code{NULL}.
273
 
51997 ripley 274
  One irregularity that is usually tolerated, however, is to optionally
275
  add other attributes to those guaranteed to exist (for example,
276
  \code{"terms"} in \code{"data.frame"} objects returned by
277
  \code{\link{model.frame}}).  As of version 2.8.0, validity checks by
278
  \code{\link{validObject}} ignore extra attributes; even if this check
279
  is tightened in the future, classes extending S3 classes would likely
280
  be exempted because extra attributes are so common.
281
}
46503 jmc 282
 
21142 ripley 283
\seealso{
284
  \code{\link{setClass}}, \code{\link{setMethod}}
285
}
21070 jmc 286
 
46128 jmc 287
\references{
51997 ripley 288
  Chambers, John M. (2008)
289
  \emph{Software for Data Analysis: Programming with R}
46128 jmc 290
  Springer.  (For the R version: see section 10.6 for method
291
  selection and section 13.4 for generic functions).
61433 ripley 292
 
51997 ripley 293
  Chambers, John M. (1998)
294
  \emph{Programming with Data}
295
  Springer (For the original S4 version.)
46128 jmc 296
}
297
 
21070 jmc 298
\examples{
41508 ripley 299
require(stats)
21142 ripley 300
setOldClass(c("mlm", "lm"))
301
setGeneric("dfResidual", function(model)standardGeneric("dfResidual"))
302
setMethod("dfResidual", "lm", function(model)model$df.residual)
21070 jmc 303
 
21142 ripley 304
## dfResidual will work on mlm objects as well as lm objects
305
myData <- data.frame(time = 1:10, y = (1:10)^.5)
306
myLm <- lm(cbind(y, y^3)  ~ time, myData)
21070 jmc 307
 
51213 maechler 308
showClass("data.frame")# to see the predefined S4 "oldClass"
309
 
56287 ripley 310
## two examples extending S3 class "lm", class "xlm" directly
311
## and "ylm" indirectly
46128 jmc 312
setClass("xlm", representation(eps = "numeric"), contains = "lm")
313
setClass("ylm", representation(header = "character"), contains = "xlm")
314
ym1 = new("ylm", myLm, header = "Example", eps = 0.)
315
## for more examples, see ?\link{S3Class}.
316
 
51213 maechler 317
utils::str(.OldClassesList)
318
 
26000 ripley 319
\dontshow{
46128 jmc 320
stopifnot(identical(dfResidual(myLm), myLm$df.residual))
321
removeClass("ylm"); removeClass("xlm")
21142 ripley 322
rm(myData, myLm)
46128 jmc 323
removeGeneric("dfResidual")}
37403 jmc 324
 
46503 jmc 325
## Examples of S3 classes with guaranteed attributes
326
## an S3 class "stamped" with a vector and  a "date" attribute
327
## Here is a generator function and an S3 print method.
328
## NOTE:  it's essential that the generator checks the attribute classes
329
stamped <- function(x, date = Sys.time()) {
330
    if(!inherits(date, "POSIXt"))
331
      stop("bad date argument")
332
    if(!is.vector(x))
333
      stop("x must be a vector")
334
    attr(x, "date") <- date
335
    class(x) <- "stamped"
336
    x
21070 jmc 337
}
46503 jmc 338
 
339
print.stamped <- function(x, ...) {
340
    print(as.vector(x))
341
    cat("Date: ",  format(attr(x,"date")), "\n")
37403 jmc 342
}
46503 jmc 343
 
344
## Now, an S4 class with the same structure:
345
setClass("stamped4", contains = "vector", representation(date = "POSIXt"))
346
 
347
## We can use the S4 class to register "stamped", with its attributes:
348
setOldClass("stamped", S4Class = "stamped4")
349
selectMethod("show", "stamped")
350
## and then remove "stamped4" to clean up
351
removeClass("stamped4")
352
\dontshow{
353
set.seed(113)}
56287 ripley 354
someLetters <- stamped(sample(letters, 10),
355
                       ISOdatetime(2008, 10, 15, 12, 0, 0))
46503 jmc 356
 
51213 maechler 357
st <- new("stamped", someLetters)
56287 ripley 358
st
359
# show() method prints the object's class, then calls the S3 print method.
46503 jmc 360
 
361
stopifnot(identical(S3Part(st, TRUE), someLetters))
362
 
363
# creating the S4 object directly from its data part and slots
364
new("stamped", 1:10, date = ISOdatetime(1976, 5, 5, 15, 10, 0))
365
 
366
\dontrun{
367
## The code in R that defines "ts" as an S4 class
51213 maechler 368
setClass("ts", contains = "structure",
369
      representation(tsp = "numeric"),
56287 ripley 370
      prototype(NA, tsp = rep(1,3)))
371
# prototype to be a legal S3 time-series
46503 jmc 372
## and now registers it as an S3 class
373
    setOldClass("ts", S4Class = "ts", where = envir)
51213 maechler 374
}
46503 jmc 375
 
376
\dontshow{
377
  removeClass("stamped")
378
  rm(someLetters, st)
379
}
380
 
381
}
21070 jmc 382
\keyword{ programming }
383
\keyword{ methods }