Rev 59039 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
% File src/library/methods/man/NextMethod.Rd% Part of the R package, http://www.R-project.org% Copyright 1995-2011 R Core Team% Distributed under GPL 2 or later\name{callNextMethod}\alias{callNextMethod}\title{Call an Inherited Method}\description{A call to \code{callNextMethod} can only appear inside a methoddefinition. It then results in a call to the first inherited methodafter the current method, with the arguments to the current methodpassed down to the next method. The value of that method call is thevalue of \code{callNextMethod}.}\usage{callNextMethod(...)}\arguments{\item{\dots}{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 \code{callNextMethod}, theeffect 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\code{callNextMethod}; see the examples.}}\details{The \sQuote{next} method (i.e., the first inherited method) is definedto be that method which \emph{would} have been called if the currentmethod did not exist. This is more-or-less literally what happens: Thecurrent method (to be precise, the method with signature given by the\code{defined} slot of the method from which \code{callNextMethod} iscalled) is deleted from a copy of the methods for the current generic,and \code{\link{selectMethod}} is called to find the next method (theresult is cached in a special object, so the search only typicallyhappens once per session per combination of argument classes).Note that the preceding definition means that the next method isdefined uniquely when \code{setMethod} inserts the method containingthe \code{callNextMethod} call, given the definitions of the classesin the signature. The choice does not depend on the path that gets usto that method (for example, through inheritance or from another\code{callNextMethod} call). This definition was not enforced inversions of \R prior to 2.3.0, where the method was selected based onthe target signature, and so could vary depending on the actualarguments.It is also legal, and often useful, for the method called by\code{callNextMethod} to itself have a call to\code{callNextMethod}. This generally works as you would expect, butfor completeness be aware that it is possible to have ambiguousinheritance in the S structure, in the sense that the same twoclasses can appear as superclasses \emph{in the opposite order} intwo other class definitions. In this case the effect of a nestedinstance of \code{callNextMethod} is not well defined. Suchinconsistent class hierarchies are both rare and nearly always theresult of bad design, but they are possible, and currently undetected.The statement that the method is called with the current arguments ismore precisely as follows. Arguments that were missing in the currentcall are still missing (remember that \code{"missing"} is a validclass in a method signature). For a formal argument, say \code{x}, thatappears in the original call, there is a corresponding argument in thenext method call equivalent to \code{x = x}. In effect, thismeans that the next method sees the same actual arguments, butarguments are evaluated only once.}\value{The value returned by the selected method.}\references{Chambers, John M. (2008)\emph{Software for Data Analysis: Programming with R}Springer. (For the R version.)Chambers, John M. (1998)\emph{Programming with Data}Springer (For the original S4 version.)}\seealso{\code{\link{callGeneric}} to call the generic function with thecurrent dispatch rules (typically for a group generic function);\link{Methods} for the general behavior of method dispatch.}\examples{## some class definitions with simple inheritancesetClass("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 callNextMethodf <- 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")))\dontshow{## a version of the example with 1 more layer of nesting## next methods calling next methods, with arguments; using group genericssetMethod("Ops", "B2",function(e1, e2) callNextMethod())setMethod("Ops", c("B0"),function(e1, e2) callNextMethod(e1@b0, e2))b2 + 1 # 11b1 == 2 # TRUEremoveClass("B2"); removeClass("B1"); removeClass("B0")removeGeneric("f")removeMethods("Ops")## tests of multiple callNextMethodsetClass("m1", representation(count = "numeric"), contains = "matrix",prototype = prototype(count = 0))mm1 <- new("m1", matrix(1:12, 3,4))setMethod("[", "m1", function(x, i, j, ..., drop) callNextMethod())setClass("m2", representation(sum = "numeric"), contains = "m1")setMethod("Ops", c("m1", "m1"), function(e1, e2) {as(e1, "matrix") <- callNextMethod()e1@count <- max(e1@count, e2@count)+1e1})mm2 <- new("m2", matrix(1:12, 3, 4), sum = sum(1:12))stopifnot(identical(mm2[,2], 4:6))setClass("m3", representation(rowtags = "character"),contains = "m2")setMethod("[", signature(x="m3", i = "character", j = "missing",drop = "missing"),function(x, i,j, ..., drop) {xx <- callNextMethod(x, match(i, x@rowtags),)x@.Data <- xxx@rowtags <- x@rowtags[match(i, x@rowtags)]x})tm <- matrix(1:12, 4, 3)mm3 <- new("m3", tm, rowtags = letters[1:4])mmm <- mm3[c("b", "d")]stopifnot(identical(mmm,new("m3", tm[c(2, 4),], rowtags = c("b", "d"))))removeClass("m3")removeClass("m2")removeClass("m1")removeMethods("[")}}\keyword{programming}\keyword{classes}\keyword{methods}