The R Project SVN R

Rev

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

Rev Author Line No. Line
46973 ripley 1
% File src/library/methods/man/S3Part.Rd
2
% Part of the R package, http://www.R-project.org
59039 ripley 3
% Copyright 2008 R Core Team
46973 ripley 4
% Distributed under GPL 2 or later
5
 
6
\name{S3Part}
56186 murdoch 7
\alias{S3Part}
46128 jmc 8
\alias{S3Part<-}
9
\alias{S3Class}
10
\alias{S3Class<-}
11
\alias{isXS3Class}
46503 jmc 12
\alias{slotsFromS3}
13
\alias{S4}
14
\alias{S3}
15
\alias{coerce,ANY,S3-method}
16
\alias{coerce,oldClass,S3-method}
17
\alias{coerce,ANY,S4-method}
18
\alias{S3-class}
19
\title{ S3-style Objects and S4-class Objects}
46128 jmc 20
\description{
21
  Old-style (S3) classes may be registered as S4 classes (by calling
22
  \code{\link{setOldClass}}, and many have been.  These classes can
23
  then be contained in (that is, superclasses of) regular S4 classes, allowing formal methods
24
  and slots to be added to the S3 behavior.  The function
61433 ripley 25
  \code{S3Part} extracts or replaces
48735 jmc 26
  the S3 part of such an object.
27
  \code{S3Class} extracts or
28
  replaces the S3-style class.  \code{S3Class} also applies to object
29
  from an S4 class with \code{S3methods=TRUE} in the call to \code{\link{setClass}}.
61433 ripley 30
 
48735 jmc 31
See the details below.
46503 jmc 32
  Also discussed are S3 <-> S4 coercion; see the section
33
  \dQuote{S3 and S4 objects}
46128 jmc 34
}
35
\usage{
36
 
46223 jmc 37
S3Part(object, strictS3 = FALSE, S3Class)
46128 jmc 38
 
46223 jmc 39
S3Part(object, strictS3 = FALSE, needClass = ) <- value
46128 jmc 40
 
41
S3Class(object)
42
 
43
S3Class(object) <-  value
44
 
45
isXS3Class(classDef)
46503 jmc 46
 
47
slotsFromS3(object)
48
 
46128 jmc 49
}
50
%- maybe also 'usage' for other objects documented here.
51
\arguments{
52
 
46223 jmc 53
  \item{object}{ An object from some class that extends a registered
54
      S3 class,
55
      usually because the class has as
56
      one of its superclasses an S3 class registered by a call to
57
      \code{\link{setOldClass}}, or from a class that extends a basic
58
      vector, matrix or array object type.  See the details.
46503 jmc 59
 
60
      For most of the functions, an S3 object can also be supplied,
61
      with the interpretation that it is its own S3 part.
46223 jmc 62
 }
63
    \item{strictS3}{  If \code{TRUE}, the value returned by
64
        \code{S3Part} will be an S3 object, with all the S4 slots
65
        removed.  Otherwise, an S4 object will always
66
        be returned; for example, from the S4 class created by
67
  \code{\link{setOldClass}} as a proxy for an S3 class, rather than
68
  the underlying S3 object.
69
        }
46128 jmc 70
  \item{S3Class}{ The character vector to be stored as the S3 class
48735 jmc 71
      slot in the object.  Usually, and by default, retains
46223 jmc 72
      the slot from \code{object}.
73
      }
74
 
75
  \item{needClass}{Require that the replacement value be this class or a
46128 jmc 76
      subclass of it.
77
      }
78
 
46503 jmc 79
  \item{value}{ For \code{S3Part<-}, the replacement value for the S3 part of the object.
46128 jmc 80
      This does \emph{not} need to be an S4 object; in fact, the
81
      usual way to create objects from these classes is by giving an
82
      S3 object of the right class as an argument to
83
      \code{\link{new}}.
46503 jmc 84
 
48735 jmc 85
      For \code{S3Class<-}, the character vector that will be used as
86
      a proxy for \code{class(x)} in S3 method dispatch.  This
87
      replacement function can be used to control S3 per-object method
88
      selection.
46128 jmc 89
    }
90
 
91
 
92
    \item{classDef}{ A class definition object, as returned by \code{\link{getClass}}.
93
        }
94
 
95
 
96
}
97
\details{
46223 jmc 98
  Classes that register S3 classes by a call to
99
  \code{\link{setOldClass}} have slot \code{".S3Class"} to hold
100
  the corresponding S3 vector of class strings.
101
  The prototype of such
102
  a class has the value for this slot determined  by the argument to
48735 jmc 103
  \code{\link{setOldClass}}.
104
  Other S4 classes will have the same slot if the argument
105
  \code{S3methods = TRUE} is supplied to \code{\link{setClass}}; in
106
  this case, the slot is set to the S4 inheritance of the class.
46223 jmc 107
 
48735 jmc 108
  New S4 classes that extend (contain) such
46223 jmc 109
  classes also have the same slot, and by default the prototype has
110
  the value determined  by the \code{contains=} argument to
111
  \code{\link{setClass}}.
112
  Individual objects from the S4 class may
61433 ripley 113
  have
46128 jmc 114
  an S3 class corresponding to the value in the prototype or to an
115
  (S3) subclass of that value.  See the examples below.
116
 
46223 jmc 117
  \code{S3Part()}  with \code{strictS3 = TRUE} constructs the underlying S3 object by eliminating
118
  all the formally defined slots and turning off the S4 bit of the
119
  object.  With  \code{strictS3 = FALSE} the object returned is from
120
  the corresponding S4 class.  For consistency and generality,
121
  \code{S3Part()} works also for classes that extend the basic vector,
122
  matrix and array classes.  Since \R is somewhat arbitrary about what
123
  it treats as an S3 class (\code{"ts"} is, but \code{"matrix"} is
124
  not), \code{S3Part()} tries to return an S3 (that is, non-S4) object
125
  whenever the S4 class has a suitable superclass, of either S3 or
126
  basic object type.
127
 
128
  One general application that relies on this generality is to use
129
  \code{S3Part()} to get a superclass object that is guaranteed not to
130
  be an S4 object.  If you are calling some function that checks for
131
  S4 objects, you need to be careful not to end up in a closed loop
132
  (\code{fooS4} calls \code{fooS3}, which checks for an S4 object and
133
  calls \code{fooS4} again, maybe indirectly).  Using \code{S3Part()}
134
  with \code{strictS3 = TRUE} is a mechanism to avoid such loops.
135
 
136
 
46128 jmc 137
  Because the contents of S3 class objects have no definition or
138
  guarantee, the computations involving S3 parts  do
48735 jmc 139
  \emph{not} check for slot validity.  Slots are implemented
46128 jmc 140
  internally in \R as attributes, which are copied when present in the
48735 jmc 141
  S3 part.  Grave problems can occur if an S4 class
46128 jmc 142
  extending an S3 class uses the name of an S3 attribute as the name
48735 jmc 143
  of an S4 slot, and S3 code sets the attribute to an object from an
144
  invalid class according to the S4 definition.
46128 jmc 145
 
46223 jmc 146
  Frequently, \code{S3Part} can and should be avoided by simply
46128 jmc 147
  coercing objects to the desired class; methods are automatically
148
  defined to deal correctly with the slots when \code{\link{as}} is
149
  called to extract or replace superclass objects.
46503 jmc 150
 
151
  The function \code{slotsFromS3()} is a generic function used
152
  internally to access the slots associated with the S3 part of the
153
  object.  Methods for this function are created automatically when
154
  \code{\link{setOldClass}} is called with the \code{S4Class}
155
  argument.  Usually, there is only one S3 slot, containing the S3
156
  class, but the \code{S4Class} argument may provide additional slots,
157
  in the case that the S3 class has some guaranteed attributes that
158
  can be used as formal S4 slots.  See the corresponding section in
159
  the documentation of \code{\link{setOldClass}}.
46128 jmc 160
}
161
\value{
162
 
46223 jmc 163
\code{S3Part}:  Returns or sets  the S3 information
46128 jmc 164
  (and possibly some S4 slots as well, depending on arguments
165
  \code{S3Class} and \code{keepSlots}).  See the discussion of
166
  argument \code{strict} above.  If it is \code{TRUE} the value
167
  returned is an S3 object.
168
 
169
 
48735 jmc 170
\code{S3Class}:  Returns or sets the character vector of S3 class(es) stored in
171
  the object, if the class has the corresponding \code{.S3Class} slot.
172
  Currently, the function defaults to \code{\link{class}} otherwise.
46128 jmc 173
 
46223 jmc 174
\code{isXS3Class}: Returns \code{TRUE} or \code{FALSE} according
46128 jmc 175
    to whether the class defined by \code{ClassDef}
176
    extends S3 classes (specifically, whether it has the slot for
177
    holding the S3 class).
46503 jmc 178
 
179
\code{slotsFromS3}: returns a list of the relevant slot classes, or an
180
empty list for any other object.
46128 jmc 181
}
182
 
46503 jmc 183
\section{S3 and S4 Objects: Conversion Mechanisms}{
184
 
185
  Objects in \R have an internal bit that indicates whether or not to
186
  treat the object as coming from an S4 class.  This bit is tested by
187
  \code{\link{isS4}} and can be set on or off by \code{\link{asS4}}.
188
  The latter function, however, does no checking or interpretation;
189
  you should only use it if you are very certain every detail has been
190
  handled correctly.
191
 
192
  As a friendlier alternative, methods have been defined for coercing
193
  to the virtual classes \code{"S3"} and \code{"S4"}.  The expressions
194
  \code{as(object, "S3")}  and \code{as(object, "S4")}  return S3
195
  and S4 objects, respectively.  In addition, they attempt
196
  to do conversions in a valid way, and also check validity when
197
  coercing to S4.
198
 
199
  The expression \code{as(object, "S3")} can be used in two ways.  For
200
  objects from one of the registered S3 classes, the expression will
201
  ensure that the class attribute is the full multi-string S3 class
202
  implied by \code{class(object)}.  If the registered class has known
203
  attribute/slots, these will also be provided.
204
 
205
  Another use of  \code{as(object, "S3")}  is to take an S4 object and
206
  turn it into an S3 object with corresponding attributes.  This is
207
  only meaningful with S4 classes that have a data part.  If you want
208
  to operate on the object without invoking S4 methods, this
209
  conversion is usually the safest way.
210
 
211
  The expression  \code{as(object, "S4")} will use the attributes in
212
  the object to create an object from the S4 definition of
213
  \code{class(object)}. This is a general mechanism to create
214
  partially defined version of S4 objects via S3 computations  (not
215
  much different from invoking \code{\link{new}} with corresponding
216
  arguments, but usable in this form even if the S4 object has an
61433 ripley 217
  initialize method with different arguments).
46503 jmc 218
}
219
 
46128 jmc 220
\references{
221
 Chambers, John M. (2008)
222
 \emph{Software for Data Analysis: Programming with R}
223
  Springer.  (For the R version).
224
 
225
 Chambers, John M. (1998)
226
 \emph{Programming with Data}
227
 Springer (For the original S4 version.)
228
}
229
\examples{
56287 ripley 230
## two examples extending S3 class "lm", class "xlm" directly
231
## and "ylm" indirectly
46128 jmc 232
setClass("xlm", representation(eps = "numeric"), contains = "lm")
233
setClass("ylm", representation(header = "character"), contains = "xlm")
234
\dontshow{
235
ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14)
236
trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69)
237
group <- gl(2,10,20, labels=c("Ctl","Trt"))
238
weight <- c(ctl, trt)
239
lm.D9 <- lm(weight ~ group)
240
}
241
## lm.D9 is as computed in the example for stats::lm
242
y1 = new("ylm", lm.D9, header = "test", eps = .1)
243
xx = new("xlm", lm.D9, eps =.1)
244
y2 = new("ylm", xx, header = "test")
245
stopifnot(inherits(y2, "lm"))
246
stopifnot(identical(y1, y2))
247
stopifnot(identical(S3Part(y1, strict = TRUE), lm.D9))
248
 
249
## note the these classes can insert an S3 subclass of "lm" as the S3 part:
250
myData <- data.frame(time = 1:10, y = (1:10)^.5)
46223 jmc 251
myLm <- lm(cbind(y, y^3)  ~ time, myData) # S3 class: c("mlm", "lm")
46128 jmc 252
ym1 = new("ylm", myLm, header = "Example", eps = 0.)
253
 
254
##similar classes to "xlm" and "ylm", but extending S3 class c("mlm", "lm")
255
setClass("xmm", representation(eps = "numeric"), contains = "mlm")
256
setClass("ymm", representation(header="character"), contains = "xmm")
257
 
258
ym2 <- new("ymm", myLm, header = "Example2", eps = .001)
259
 
260
# but for class "ymm", an S3 part of class "lm" is an error:
261
try(new("ymm", lm.D9, header = "Example2", eps = .001))
262
 
56287 ripley 263
setClass("dataFrameD", representation(date = "Date"),
264
         contains = "data.frame")
46128 jmc 265
myDD <- new("dataFrameD", myData, date = Sys.Date())
266
 
46223 jmc 267
## S3Part() applied to classes with a data part (.Data slot)
268
 
269
setClass("NumX", contains="numeric", representation(id="character"))
270
nn = new("NumX", 1:10, id="test")
271
stopifnot(identical(1:10, S3Part(nn, strict = TRUE)))
61433 ripley 272
 
46223 jmc 273
m1 = cbind(group, weight)
274
setClass("MatX", contains = "matrix", representation(date = "Date"))
275
mx1 = new("MatX", m1, date = Sys.Date())
276
stopifnot(identical(m1, S3Part(mx1, strict = TRUE)))
277
 
46128 jmc 278
\dontshow{
279
 
56287 ripley 280
for(cl in c("ylm", "xlm", "ymm", "xmm", "dataFrameD", "NumX", "MatX"))
281
    removeClass(cl)
46128 jmc 282
 
283
}
284
}
285
\seealso{  \code{\link{setOldClass}} }
286
\keyword{ programming }
287
\keyword{ classes }