The R Project SVN R

Rev

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

Rev Author Line No. Line
15357 jmc 1
\name{setMethod}
2
\alias{setMethod}
17454 jmc 3
\alias{removeMethod}
15357 jmc 4
\title{ Create and Save a Method }
5
\description{
6
  Create and save a formal method for a given function and list of classes.
7
}
8
\usage{
26530 maechler 9
setMethod(f, signature=character(), definition, where= topenv(parent.frame()),
10
          valueClass = NULL, sealed = FALSE)
17454 jmc 11
 
12
removeMethod(f, signature, where)
15357 jmc 13
}
14
\arguments{
15
  \item{f}{ The character-string name of the generic function. }
16
  \item{signature}{ A match of formal argument names for \code{f} with
19029 hornik 17
    the character-string names of corresponding classes.  This
18
    argument can also just be the vector of class names, in which case
19
    the first name corresponds to the first formal argument, the
20
    next to the second formal argument, etc.}
15826 jmc 21
  \item{definition}{ A function definition, which will become the method
19029 hornik 22
    called when the arguments in a call to \code{f} match the
23
    classes in \code{signature}, directly or through inheritance. }
26530 maechler 24
  \item{where}{the database in which to store the definition of the
25
    method; % FIXME: by default, the ... environment.
17454 jmc 26
 
19029 hornik 27
    For \code{removeMethod}, the default is the location of the (first)
28
    instance of the method for this signature.}
15357 jmc 29
  \item{valueClass}{ If supplied, this argument asserts that the
19029 hornik 30
    method will return a value of this class.  (At present this
31
    argument is stored but not explicitly used.) }
23493 jmc 32
  \item{sealed}{ If \code{TRUE}, the method so defined cannot be
33
      redefined by another call to \code{setMethod} (although it can
34
      be removed and then re-assigned).  Note that this argument is an
35
      extension to the definition of \code{setMethod} in the reference.}
15357 jmc 36
}
17454 jmc 37
\value{
19029 hornik 38
  These functions exist for their side-effect, in setting or removing a
39
  method in the object defining methods for the specified generic.
17454 jmc 40
 
19029 hornik 41
  The value returned by \code{removeMethod} is \code{TRUE} if a method
42
  was found to be removed.
17454 jmc 43
}
15357 jmc 44
\details{
45
  R methods for a particular generic function are stored in an object
23678 jmc 46
  of class \code{\link{MethodsList}}.  The effect of calling
15826 jmc 47
  \code{setMethod} is to store \code{definition}  in a \code{MethodsList}
23678 jmc 48
  object on database \code{where}.   If \code{f} doesn't
15357 jmc 49
  exist as a generic function, but there is an ordinary function of
50
  the same name and the same formal arguments, a new generic function
51
  is created, and the previous non-generic version of \code{f} becomes
23678 jmc 52
  the default method.  This is equivalent to the programmer calling
53
  \code{\link{setGeneric}} for the same function; it's better practice
54
  to do the call explicitly, since it shows that you intend to turn
55
  \code{f} into a generic function.
15357 jmc 56
 
23678 jmc 57
  Methods are stored in a hierarchical structure:  see
58
  \link{Methods} for how the objects are used to select a method, and
59
  \code{\link{MethodsList}} for functions that manipulate the objects.
60
 
61
 The class
15357 jmc 62
  names in the signature can be any formal class, plus predefined basic
63
  classes such as \code{"numeric"}, \code{"character"}, and
64
  \code{"matrix"}.  Two additional special class names can appear:
65
  \code{"ANY"}, meaning that this argument can have any class at all;
66
  and \code{"missing"}, meaning that this argument \emph{must not}
67
  appear in the call in order to match this signature.  Don't confuse
68
  these two:  if an argument isn't mentioned in a signature, it
69
  corresponds implicitly to class \code{"ANY"}, not to
25118 hornik 70
  \code{"missing"}.  See the example below.  Old-style (\dQuote{S3})
71
  classes can also be used, if you need compatibility with these, but
72
  you should definitely declare these classes by calling
23678 jmc 73
  \code{\link{setOldClass}} if you want S3-style inheritance to work.
15357 jmc 74
 
23678 jmc 75
 
15357 jmc 76
  While \code{f} can correspond to methods defined on several packages
19087 jmc 77
  or environments, the underlying model is that these together make up
15357 jmc 78
  the definition for a single generic function.  When R proceeds to
79
  select and evaluate methods for \code{f}, the methods on the current
23678 jmc 80
  search list are merged to form a single methods list.  When \code{f}
25118 hornik 81
  is called and a method is \dQuote{dispatched}, the evaluator matches the
23678 jmc 82
  classes of the actual arguments to the signatures of the available
83
  methods.  When a match is found, the body of the corresponding
84
  method is evaluated (in R, the body is evaluated in the lexical
85
  context of the method), but without rematching the arguments to
86
  \code{f}.
87
 
88
  It is possible, however, to have some differences between the
89
  formal arguments to a method supplied to \code{setMethod} and those
90
  of the generic. Roughly, if the generic has \dots as one of its
91
  arguments, then the method may have extra formal arguments, which
92
  will be matched from the arguments matching \dots in the call to
93
  \code{f}.  (What actually happens is that a local function is
94
  created inside the method, with its formal arguments, and the method
95
  is re-defined to call that local function.)
26530 maechler 96
 
23678 jmc 97
  Method dispatch tries to match the class of the actual arguments in a
98
  call to the available methods collected for \code{f}.  Roughly, for
99
  each formal argument in turn, we look for the best match (the exact
100
  same class or the nearest element in the value of
101
  \code{\link{extends}} for that class) for which there is any
102
  possible method matching the remaining arguments.  See
103
  \link{Methods} for more details.
104
 
15357 jmc 105
}
106
\references{
25118 hornik 107
  The R package \pkg{methods} implements, with a few exceptions, the
108
  programming interface for classes and methods in the book
109
  \emph{Programming with Data} (John M. Chambers, Springer, 1998), in
110
  particular sections 1.6, 2.7, 2.8, and chapters 7 and 8.
15357 jmc 111
 
25118 hornik 112
  While the programming interface for the \pkg{methods} package follows
113
  the reference, the R software is an original implementation, so
114
  details in the reference that reflect the S4 implementation may appear
21001 jmc 115
  differently in R.  Also, there are extensions to the programming
116
  interface developed more recently than the reference.  For a
26530 maechler 117
  discussion of details and ongoing development, see the web page
21001 jmc 118
  \url{http://developer.r-project.org/methodsPackage.html} and the
119
  pointers from that page.
15357 jmc 120
}
121
\examples{
27464 ripley 122
\dontshow{  require(stats)
15357 jmc 123
  setClass("track",
124
    representation(x="numeric", y = "numeric"))
17454 jmc 125
  setClass("trackCurve", representation("track",
126
    smooth = "numeric"))
21001 jmc 127
  setClass("trackMultiCurve", representation(x="numeric", y="matrix", smooth="matrix"),
128
          prototype = list(x=numeric(), y=matrix(0,0,0), smooth=
129
  matrix(0,0,0)))
15357 jmc 130
}
17376 jmc 131
 
15357 jmc 132
## methods for plotting track objects (see the example for \link{setClass})
133
##
134
## First, with only one object as argument:
17376 jmc 135
setMethod("plot", signature(x="track", y="missing"),
136
  function(x,  y, ...) plot(slot(x, "x"), slot(x, "y"), ...)
15357 jmc 137
)
138
## Second, plot the data from the track on the y-axis against anything
139
## as the x data.
17376 jmc 140
setMethod("plot", signature(y = "track"),
141
 function(x, y, ...) plot(x, slot(y, "y"), ...)
15357 jmc 142
)
143
## and similarly with the track on the x-axis (using the short form of
144
## specification for signatures)
17376 jmc 145
setMethod("plot", "track",
146
 function(x, y, ...) plot(slot(x, "y"), y,  ...)
15357 jmc 147
)
17239 jmc 148
t1 <- new("track", x=1:20, y=(1:20)^2)
15357 jmc 149
tc1 <- new("trackCurve", t1)
16707 jmc 150
slot(tc1, "smooth") <- smooth.spline(slot(tc1, "x"), slot(tc1, "y"))$y #$
17376 jmc 151
plot(t1)
152
plot(qnorm(ppoints(20)), t1)
18151 jmc 153
## An example of inherited methods, and of conforming method arguments
154
## (note the dotCurve argument in the method, which will be pulled out
155
## of ... in the generic.
17376 jmc 156
setMethod("plot", c("trackCurve", "missing"),
18151 jmc 157
function(x, y, dotCurve = FALSE, ...) {
17376 jmc 158
  plot(as(x, "track"))
15357 jmc 159
  if(length(slot(x, "smooth") > 0))
18151 jmc 160
    lines(slot(x, "x"), slot(x, "smooth"),
161
         lty = if(dotCurve) 2 else 1)
15357 jmc 162
  }
163
)
164
## the plot of tc1 alone has an added curve; other uses of tc1
165
## are treated as if it were a "track" object.
18151 jmc 166
plot(tc1, dotCurve = TRUE)
17376 jmc 167
plot(qnorm(ppoints(20)), tc1)
16576 jmc 168
 
169
## defining methods for a special function.
16707 jmc 170
## Although "[" and "length" are not ordinary functions
171
## methods can be defined for them.
16576 jmc 172
setMethod("[", "track",
173
  function(x, i, j, ..., drop) {
174
    x@x <- x@x[i]; x@y <- x@y[i]
175
    x
176
  })
17376 jmc 177
plot(t1[1:15])
16576 jmc 178
 
16707 jmc 179
setMethod("length", "track", function(x)length(x@y))
180
length(t1)
181
 
17761 jmc 182
## methods can be defined for missing arguments as well
183
setGeneric("summary") ## make the function into a generic
184
 
185
## A method for summary()
186
## The method definition can include the arguments, but
187
## if they're omitted, class "missing" is assumed.
188
 
189
setMethod("summary", "missing", function() "<No Object>")
190
 
26000 ripley 191
\dontshow{
17761 jmc 192
 
193
stopifnot(identical(summary(), "<No Object>"))
194
 
16707 jmc 195
## for the primitives
196
## inherited methods
197
 
198
length(tc1)
199
tc1[-1]
200
 
16576 jmc 201
## make sure old-style methods still work.
202
t11 <- t1[1:15]
203
identical(t1@y[1:15], t11@y)
204
 
205
## S3 methods, with nextMethod
206
form <- y ~ x
207
form[1]
16866 jmc 208
 
209
## S3 arithmetic methods
210
ISOdate(1990, 12, 1)- ISOdate(1980, 12, 1)
211
 
19473 jmc 212
## group methods
16866 jmc 213
 
19473 jmc 214
setMethod("Arith", c("track", "numeric"), function(e1, e2){e1@y <-
215
  callGeneric(e1@y , e2); e1})
16866 jmc 216
 
19473 jmc 217
 
16866 jmc 218
t1  - 100.
219
 
19473 jmc 220
t1/2
221
 
222
 
16866 jmc 223
## check it hasn't screwed up S3 methods
224
ISOdate(1990, 12, 1)- ISOdate(1980, 12, 1)
225
 
21865 jmc 226
## test the .Generic mechanism
227
 
228
setMethod("Compare", signature("track", "track"),
229
  function(e1,e2) {
230
  switch(.Generic,
231
   "==" = e1@y == e2@y,
232
  NA)
233
 })
234
 
235
#stopifnot(all(t1==t1))
236
#stopifnot(identical(t1<t1, NA))
237
 
238
 
21001 jmc 239
## A test of nested calls to "[" with matrix-style arguments
240
## applied to data.frames (S3 methods)
241
 
242
setMethod("[", c("trackMultiCurve", "numeric", "numeric"), function(x, i, j, ..., drop) {
243
### FIXME:  a better version has only 1st arg in signature
244
### and uses callNextMethod, when this works with primitives.
245
    x@y <- x@y[i, j, drop=FALSE]
246
    x@x <- x@x[i]
247
    x
248
})
249
 
250
 
251
"testFunc" <-
252
function(cur) {
253
    sorted <- cur[order(cur[,1]),]
254
    sorted[ !is.na(sorted[,1]), ]
255
}
256
 
257
Nrow <- 1000 # at one time, values this large triggered a bug in gc/protect
258
## the loop here was a trigger for the bug
259
Niter <- 10
260
for(i in 1:Niter)  {
261
    yy <- matrix(rnorm(10*Nrow), 10, Nrow)
262
    tDF <- as.data.frame(yy)
263
    testFunc(tDF)
264
}
265
 
266
 
267
tMC <- new("trackMultiCurve", x=seq(length=Nrow), y = yy)
268
## not enough functions have methods for this class to use testFunc
269
 
270
stopifnot(identical(tMC[1:10, 1:10]@y, yy[1:10, 1:10]))
271
 
272
 
17454 jmc 273
## verify we can remove methods and generic
274
 
17761 jmc 275
removeMethods("-")
23305 ripley 276
removeMethod("length", "track")
21865 jmc 277
removeMethods("Arith")
278
removeMethods("Compare")
17454 jmc 279
 
17761 jmc 280
## repeat the test one more time on the primitives
281
 
282
length(ISOdate(1990, 12, 1)- ISOdate(1980, 12, 1))
283
 
21875 jmc 284
## methods for %*%, which isn't done by the same C code as other ops
285
 
286
setClass("foo", representation(m="matrix"))
287
m1 <- matrix(1:12,3,4)
288
f1 = new("foo", m=m1)
289
f2 = new("foo", m=t(m1))
290
 
291
setMethod("\%*\%", c("foo", "foo"),
292
 function(x,y)callGeneric(x@m, y@m))
293
 
294
stopifnot(identical(f1\%*\%f2, m1\%*\% t(m1)))
295
 
296
removeMethods("\%*\%")
297
 
17761 jmc 298
removeMethods("plot")
299
 
300
stopifnot(existsFunction("plot", FALSE) && !isGeneric("plot", 1))
301
 
17454 jmc 302
## methods for plotData
303
plotData <- function(x, y, ...) plot(x, y, ...)
304
 
305
setGeneric("plotData")
306
 
307
setMethod("plotData", signature(x="track", y="missing"),
308
  function(x,  y, ...) plot(slot(x, "x"), slot(x, "y"), ...)
309
)
310
## and now remove the whole generic
17761 jmc 311
removeGeneric("plotData")
312
 
17454 jmc 313
stopifnot(!exists("plotData", 1))
314
 
18413 jmc 315
##  Tests of method inheritance & multiple dispatch
316
setClass("A0", representation(a0 = "numeric"))
18380 jmc 317
 
18413 jmc 318
setClass("A1", representation("A0", a1 = "character"))
319
 
320
setClass("B0" ,representation(b0 = "numeric"))
321
 
322
setClass("B1", "B0")
323
 
324
setClass("B2", representation("B1", b2 = "logical"))
325
 
326
setClass("AB0", representation("A1", "B2", ab0 = "matrix"))
327
 
328
f1 <- function(x,  y)"ANY"
329
 
330
setGeneric("f1")
331
 
332
setMethod("f1", c("A0", "B1"), function(x, y)"A0 B1")
333
setMethod("f1", c("B1", "A0"), function(x, y)"B1 A0")
334
 
335
a0 <- new("A0")
336
a1 <- new("A1")
337
b0 <- new("B0")
338
b1 <- new("B1")
339
b2 <- new("B2")
340
 
341
deparseText <- function(expr)
342
    paste(deparse(expr), collapse = "\\  ")
343
 
344
mustEqual <- function(e1, e2){
345
    if(!identical(e1, e2))
346
        stop(paste("!identical(", deparseText(substitute(e1)),
347
                   ", ", deparseText(substitute(e2)), ")", sep=""))
15357 jmc 348
}
18413 jmc 349
 
350
mustEqual(f1(a0, b0), "ANY")
351
mustEqual(f1(a1,b0), "ANY")
352
mustEqual(f1(a1,b1), "A0 B1")
353
mustEqual(f1(b1,a1), "B1 A0")
354
mustEqual(f1(b1,b1), "ANY")
355
 
20330 jmc 356
## remove classes:  order matters so as not to undefine earlier classes
357
for(.cl in c("AB0", "A1", "A0", "B2", "B1", "B0"))
18413 jmc 358
    removeClass(.cl)
359
 
360
removeGeneric("f1")
361
 
19670 jmc 362
## test of nonstandard generic definition
18413 jmc 363
 
19670 jmc 364
setGeneric("doubleAnything", function(x) {
365
  methodValue <- standardGeneric("doubleAnything")
366
  c(methodValue, methodValue)
367
})
18413 jmc 368
 
19670 jmc 369
setMethod("doubleAnything", "ANY", function(x)x)
370
 
371
setMethod("doubleAnything", "character",
372
function(x)paste("<",x,">",sep=""))
373
 
374
mustEqual(doubleAnything(1:10), c(1:10, 1:10))
375
mustEqual(doubleAnything("junk"), rep("<junk>",2))
376
 
377
removeGeneric("doubleAnything")
378
 
379
 
16576 jmc 380
}
18413 jmc 381
}
15357 jmc 382
 
17454 jmc 383
\seealso{ \link{Methods}, \code{\link{MethodsList}} for details of the
384
  implementation}
15357 jmc 385
 
386
\keyword{programming}
387
\keyword{classes}
17454 jmc 388
\keyword{classes}
15357 jmc 389
\keyword{methods}