Rev 39360 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
\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 \dQuote{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 \dQuote{\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{The R package \pkg{methods} implements, with a few exceptions, theprogramming interface for classesand methods in the book \emph{Programming with Data} (JohnM. Chambers, Springer, 1998), in particular sections 1.6, 2.7, 2.8,and chapters 7 and 8.While the programming interface for the \pkg{methods} package followsthe reference, the R software is an original implementation, sodetails in the reference that reflect the S4 implementation may appeardifferently in R. Also, there are extensions to the programminginterface developed more recently than the reference. For adiscussion of details see \code{?\link{Methods}}and the links from that documentation.}\seealso{\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)f(b1)\dontshow{stopifnot(identical(f(b2), c(b2@b2, paste(b2@b1,":"), b2@b0^2, "B2")))## 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}