| 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 }
|