The R Project SVN R

Rev

Rev 71937 | 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/NextMethod.Rd
68948 ripley 2
% Part of the R package, https://www.R-project.org
71956 ripley 3
% Copyright 1995-2017 R Core Team
42333 ripley 4
% Distributed under GPL 2 or later
5
 
18558 jmc 6
\name{callNextMethod}
56186 murdoch 7
\alias{callNextMethod}
18558 jmc 8
\title{Call an Inherited Method}
9
\description{
10
  A call to \code{callNextMethod} can only appear inside a method
11
  definition.  It then results in a call to the first inherited method
12
  after the current method, with the arguments to the current method
13
  passed down to the next method.  The value of that method call is the
14
  value of \code{callNextMethod}.
15
}
16
\usage{
21345 jmc 17
callNextMethod(...)
18558 jmc 18
}
21345 jmc 19
\arguments{
20
  \item{\dots}{
38402 ripley 21
    Optionally, the arguments to the function in its next call
22
    (but note that the dispatch is as in the detailed description below;
44506 maechler 23
    the arguments have no effect on selecting the next method.)
23838 jmc 24
 
38402 ripley 25
    If no arguments are included in the call to \code{callNextMethod}, the
23898 jmc 26
    effect is to call the method with the current arguments.
27
    See the detailed description for what this really means.
28
 
38402 ripley 29
    Calling with no arguments is often the natural way to use
23898 jmc 30
    \code{callNextMethod}; see the examples.
21345 jmc 31
    }
32
}
18558 jmc 33
\details{
42963 ripley 34
  The \sQuote{next} method (i.e., the first inherited method) is defined
38402 ripley 35
  to be that method which \emph{would} have been called if the current
36
  method did not exist. This is more-or-less literally what happens: The
37
  current method (to be precise, the method with signature given by the
38
  \code{defined} slot of the method from which \code{callNextMethod} is
39
  called) is deleted from a copy of the methods for the current generic,
40
  and \code{\link{selectMethod}} is called to find the next method (the
71937 jmc 41
  result is cached in the method object where the call occurred, so the search typically
42
  happens only once per session per combination of argument classes).
44506 maechler 43
 
71937 jmc 44
  The next method is defined from the \emph{signature} of the current
45
  method, not from the actual classes of the arguments.
46
  In particular, modifying any of the arguments has no effect on the
47
  selection.
48
  As a result, the selected next method can be called with invalid
49
  arguments if the calling function assigns objects of a different
50
  class before the \code{callNextMethod()} call.
51
  Be careful of any assignments to such arguments.
18558 jmc 52
 
71937 jmc 53
  It is possible for the selection of the next method to be ambiguous,
54
  even though the original set of methods was consistent.
55
  See the section \dQuote{Ambiguous Selection}.
18558 jmc 56
 
57
  The statement that the method is called with the current arguments is
58
  more precisely as follows.  Arguments that were missing in the current
59
  call are still missing (remember that \code{"missing"} is a valid
60
  class in a method signature).  For a formal argument, say \code{x}, that
61
  appears in the original call, there is a corresponding argument in the
42963 ripley 62
  next method call equivalent to \code{x = x}.  In effect, this
18558 jmc 63
  means that the next method sees the same actual arguments, but
64
  arguments are evaluated only once.
65
}
71937 jmc 66
\section{Ambiguous Selection}{
67
There are two fairly common situations in which the choice of a next
68
method is ambiguous, even when the original set of methods uniquely
69
defines all method selection unambiguously.
70
In these situations, \code{callNextMethod()} should be replaced,
71
either by a call to a specific function or by recalling the generic
72
with different arguments.
73
 
74
The most likely situation arises with methods for binary operators,
75
typically through one of the group generic functions.
76
See the example for class \code{"rnum"} below.
77
Examples of this sort usually require three methods: two for the case
78
that the first or the second argument comes from the class, and a
79
third for the case that both arguments come from the class.
80
If that last method uses \code{callNextMethod}, the other two methods
81
are equally valid.  The ambiguity is exactly the same that required
82
defining the two-argument method in the first place.
83
 
84
In fact, the two possibilities are equally valid conceptually as well
85
as formally.
86
As in the example below, the logic of the application usually requires
87
selecting a computation explicitly or else calling the generic
88
function with modified arguments to select an appropriate method.
89
 
90
The other likely source of ambiguity arises from a class that inherits
91
directly from more than one other class (a \dQuote{mixin} in standard
92
terminology).
93
If the generic has methods corresponding to both superclasses, a
94
method for the current class is again needed to resolve ambiguity.
95
Using \code{callNextMethod} will again reimpose the ambiguity.
96
Again, some explicit choice has to be made in the calling method
97
instead.
98
 
99
These ambiguities are not the result of bad design, but they do
100
require workarounds.
101
Other ambiguities usually reflect inconsistencies in the tree of
102
inheritances, such as a class appearing in more than one place among
103
the superclasses.
104
Such cases should be rare, but with the independent definition of
105
classes in multiple packages, they can't be ruled out.
106
 
107
}
18558 jmc 108
\value{
109
  The value returned by the selected method.
110
}
111
\references{
71937 jmc 112
  Chambers, John M. (2016)
113
 \emph{Extending R},
114
  Chapman & Hall.
115
(Chapters 9 and 10.)
18558 jmc 116
}
56211 maechler 117
\seealso{\code{\link{callGeneric}} to call the generic function with the
118
 current dispatch rules (typically for a group generic function);
71366 jmc 119
 \link{Methods_Details} for the general behavior of method dispatch.
56211 maechler 120
}
18558 jmc 121
 
18976 jmc 122
\examples{
71937 jmc 123
## callNextMethod() used for the Math, Math2 group generic functions
18558 jmc 124
 
71937 jmc 125
## A class to automatically round numeric results to "d" digits
18558 jmc 126
 
71937 jmc 127
rnum <- setClass("rnum", slots = c(d = "integer"), contains = "numeric")
18558 jmc 128
 
71937 jmc 129
## Math functions operate on the rounded numbers, return a plain
130
## vector.  The next method will always be the default, usually a primitive.
131
setMethod("Math", "rnum",
132
          function(x)
133
              callNextMethod(round(as.numeric(x), x@d)))
134
setMethod("Math2", "rnum",
135
          function(x, digits)
136
              callNextMethod(round(as.numeric(x), x@d), digits))
18558 jmc 137
 
71937 jmc 138
## Examples of callNextMethod with two arguments in the signature.
18558 jmc 139
 
71937 jmc 140
## For arithmetic and one rnum with anything, callNextMethod with no arguments
141
## round the full accuracy result, and return as plain vector
142
setMethod("Arith", c(e1 ="rnum"),
143
          function(e1, e2)
144
              as.numeric(round(callNextMethod(), e1@d)))
145
setMethod("Arith", c(e2 ="rnum"),
146
          function(e1, e2)
147
              as.numeric(round(callNextMethod(), e2@d)))
18558 jmc 148
 
71937 jmc 149
## A method for BOTH arguments from "rnum" would be ambiguous
150
## for callNextMethod(): the two methods above are equally valid.
151
## The method chooses the smaller number of digits,
152
## and then calls the generic function, postponing the method selection
153
## until it's not ambiguous.
154
setMethod("Arith", c(e1 ="rnum", e2 = "rnum"),
155
          function(e1, e2) {
156
              if(e1@d <= e2@d)
157
                  callGeneric(e1, as.numeric(e2))
158
              else
159
                  callGeneric(as.numeric(e1), e2)
160
          })
18558 jmc 161
 
71937 jmc 162
## For comparisons, callNextMethod with the rounded arguments
163
setMethod("Compare", c(e1 = "rnum"),
164
          function(e1, e2)
165
              callNextMethod(round(e1, e1@d), round(e2, e1@d)))
166
setMethod("Compare", c(e2 = "rnum"),
167
          function(e1, e2)
168
              callNextMethod(round(e1, e2@d), round(e2, e2@d)))
18558 jmc 169
 
71937 jmc 170
## similarly to the Arith case, the method for two "rnum" objects
171
## can not unambiguously use callNextMethod().  Instead, we rely on
172
## The rnum() method inhertited from Math2 to return plain vectors.
173
setMethod("Compare", c(e1 ="rnum", e2 = "rnum"),
174
          function(e1, e2) {
175
              d <- min(e1@d, e2@d)
176
              callGeneric(round(e1, d), round(e2, d))
177
          })
178
 
179
 
180
 
181
 
182
set.seed(867)
183
 
184
x1 <- rnum(10*runif(5), d=1L)
185
x2 <- rnum(10*runif(5), d=2L)
186
 
187
x1+1
188
x2*2
189
x1-x2
190
 
191
## Simple examples to illustrate callNextMethod with and without arguments
192
B0 <- setClass("B0", slots = c(s0 = "numeric"))
193
 
194
## and a function to illustrate callNextMethod
195
 
196
f <- function(x, text = "default") {
197
    str(x) # print a summary
198
    paste(text, ":", class(x))
199
}
200
 
201
setGeneric("f")
202
setMethod("f", "B0", function(x, text = "B0") {
203
    cat("B0 method called with s0 =", x@s0, "\n")
204
    callNextMethod()
205
})
206
 
207
b0 <- B0(s0 = 1)
208
 
209
## call f() with 2 arguments: callNextMethod passes both to the default method
210
f(b0, "first test")
211
 
212
## call f() with 1 argument:  the default "B0" is not passed by callNextMethod
213
f(b0)
214
 
215
## Now, a class that extends B0, with no methods for f()
216
B1 <- setClass("B1", slots = c(s1 = "character"), contains = "B0")
217
b1 <- B1(s0 = 2, s1 = "Testing B1")
218
 
219
## the two cases work as before, by inheriting the "B0" method
220
 
221
f(b1, b1@s1)
222
 
18558 jmc 223
f(b1)
224
 
71937 jmc 225
B2 <- setClass("B2", contains = "B1")
226
 
227
## And, a method for "B2" that calls with explicit arguments.
228
## Note that the method selection in callNextMethod
229
## uses the class of the *argument* to consistently select the "B0" method
230
 
231
setMethod("f", "B2", function(x, text = "B1 method") {
232
    y <- B1(s0 = -x@s0, s1 ="Modified x")
233
    callNextMethod(y, text)
234
})
235
 
236
b2 <- B2(s1 = "Testing B2", s0 = 10)
237
 
238
f(b2, b2@s1)
239
 
44506 maechler 240
f(b2)
241
 
23898 jmc 242
 
71937 jmc 243
## Be careful:  the argument passed must be legal for the method selected
244
## Although the argument here is numeric, it's still the "B0" method that's called
245
setMethod("f", "B2", function(x, text = "B1 method") {
246
    callNextMethod(x@s0, text)
247
})
23898 jmc 248
 
71937 jmc 249
##  Now the call will cause an error:
23898 jmc 250
 
71937 jmc 251
tryCatch(f(b2), error = function(e) cat(e$message,"\n"))
23898 jmc 252
 
71937 jmc 253
 
254
\dontshow{
255
##$
23898 jmc 256
removeClass("B2"); removeClass("B1"); removeClass("B0")
257
 
258
removeGeneric("f")
259
 
71937 jmc 260
removeMethods(all=FALSE,"Arith"); removeMethods(all=FALSE,"Compare")
261
removeMethods(all=FALSE,"Math"); removeMethods(all=FALSE,"Math2")
23898 jmc 262
 
24563 ripley 263
## tests of multiple callNextMethod
71228 maechler 264
setClass("m1", slots = c(count = "numeric"), contains = "matrix",
24563 ripley 265
         prototype = prototype(count = 0))
266
mm1 <- new("m1", matrix(1:12, 3,4))
267
setMethod("[", "m1", function(x, i, j, ..., drop) callNextMethod())
268
 
71228 maechler 269
setClass("m2", slots = c(sum = "numeric"), contains = "m1")
24563 ripley 270
 
271
setMethod("Ops", c("m1", "m1"), function(e1, e2) {
272
    as(e1, "matrix") <- callNextMethod()
273
    e1@count <- max(e1@count, e2@count)+1
274
    e1})
275
 
276
mm2 <- new("m2", matrix(1:12, 3, 4), sum = sum(1:12))
277
 
278
stopifnot(identical(mm2[,2], 4:6))
279
 
71228 maechler 280
setClass("m3", slots = c(rowtags = "character"),contains = "m2")
24563 ripley 281
 
56211 maechler 282
setMethod("[", signature(x="m3", i = "character", j = "missing",
283
                         drop = "missing"),
24563 ripley 284
          function(x, i,j, ..., drop) {
285
              xx <- callNextMethod(x, match(i, x@rowtags),)
286
              x@.Data <- xx
287
              x@rowtags <- x@rowtags[match(i, x@rowtags)]
288
              x})
289
 
56211 maechler 290
tm <- matrix(1:12, 4, 3)
24563 ripley 291
 
56211 maechler 292
mm3 <- new("m3", tm, rowtags = letters[1:4])
24563 ripley 293
 
56211 maechler 294
mmm <- mm3[c("b", "d")]
24563 ripley 295
 
56211 maechler 296
stopifnot(identical(mmm,
297
      new("m3", tm[c(2, 4),], rowtags = c("b", "d"))))
24563 ripley 298
 
299
removeClass("m3")
300
removeClass("m2")
301
removeClass("m1")
302
 
71937 jmc 303
removeMethods(all=FALSE,"[")
304
removeMethods(all=FALSE,"Ops")
18558 jmc 305
}
23898 jmc 306
 
307
}
18558 jmc 308
\keyword{programming}
309
\keyword{classes}
310
\keyword{methods}