callNextMethod            package:methods            R Documentation

Call an Inherited Method

Description:

     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'.

Usage:

     callNextMethod(...)

Arguments:

     ...: 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 'callNextMethod',
          the effect is to call the method with the current arguments.
          See the detailed description for what this really means.

          Calling with no arguments is often the natural way to use
          'callNextMethod'; see the examples. 

Details:

     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.

Value:

     The value returned by the selected method.

References:

     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.)

See Also:

     '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

Examples:

     ## 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")))

