callNextMethod {methods} | R Documentation |
A call to callNextMethod
can only appear inside a method
definition. It then results in a call to the first inherited method
after the current method, with the arguments to the current method
passed down to the next method. The value of that method call is the
value of callNextMethod
.
callNextMethod(...)
... |
Optionally, the arguments to the function in its next call (but note that the dispatch is as in the detailed description below; the arguments have no effect on selecting the next method.) If no arguments are included in the call to Calling with no arguments is often the natural way to use
|
The ‘next’ method (i.e., the first inherited method) is defined
to be that method which would have been called if the current
method did not exist. This is more-or-less literally what happens: The
current method (to be precise, the method with signature given by the
defined
slot of the method from which callNextMethod
is
called) is deleted from a copy of the methods for the current generic,
and selectMethod
is called to find the next method (the
result is cached in a special object, so the search only typically
happens once per session per combination of argument classes).
Note that the preceding definition means that the next method is
defined uniquely when setMethod
inserts the method containing
the callNextMethod
call, given the definitions of the classes
in the signature. The choice does not depend on the path that gets us
to that method (for example, through inheritance or from another
callNextMethod
call). This definition was not enforced in
versions of R prior to 2.3.0, where the method was selected based on
the target signature, and so could vary depending on the actual
arguments.
It is also legal, and often useful, for the method called by
callNextMethod
to itself have a call to
callNextMethod
. This generally works as you would expect, but
for completeness be aware that it is possible to have ambiguous
inheritance in the S structure, in the sense that the same two
classes can appear as superclasses in the opposite order in
two other class definitions. In this case the effect of a nested
instance of callNextMethod
is not well defined. Such
inconsistent class hierarchies are both rare and nearly always the
result of bad design, but they are possible, and currently undetected.
The statement that the method is called with the current arguments is
more precisely as follows. Arguments that were missing in the current
call are still missing (remember that "missing"
is a valid
class in a method signature). For a formal argument, say x
, that
appears in the original call, there is a corresponding argument in the
next method call equivalent to x = x
. In effect, this
means that the next method sees the same actual arguments, but
arguments are evaluated only once.
The value returned by the selected method.
Chambers, John M. (2008) Software for Data Analysis: Programming with R Springer. (For the R version.)
Chambers, John M. (1998) Programming with Data Springer (For the original S4 version.)
callGeneric
to call the generic function with the current
dispatch rules (typically for a group generic function); Methods for the general behavior of method dispatch
## some class definitions with simple inheritance
setClass("B0" , representation(b0 = "numeric"))
setClass("B1", representation(b1 = "character"), contains = "B0")
setClass("B2", representation(b2 = "logical"), contains = "B1")
## and a rather silly function to illustrate callNextMethod
f <- function(x) class(x)
setMethod("f", "B0", function(x) c(x@b0^2, callNextMethod()))
setMethod("f", "B1", function(x) c(paste(x@b1,":"), callNextMethod()))
setMethod("f", "B2", function(x) c(x@b2, callNextMethod()))
b1 <- new("B1", b0 = 2, b1 = "Testing")
b2 <- new("B2", b2 = FALSE, b1 = "More testing", b0 = 10)
f(b2)
stopifnot(identical(f(b2), c(b2@b2, paste(b2@b1,":"), b2@b0^2, "B2")))
f(b1)
## a sneakier method: the *changed* x is used:
setMethod("f", "B2", function(x) {x@b0 <- 111; c(x@b2, callNextMethod())})
f(b2)
stopifnot(identical(f(b2), c(b2@b2, paste(b2@b1,":"), 111^2, "B2")))