Вопрос

My question:

Why is callNextMethod() not passing arguments as expected to the next method?

Situation:

Say I have two hierarchical classes foo and bar (bar is subclass of foo) for which I have a method foobar that can dispatch for both classes (i.e., has methods for both classes).

Furthermore, the method for the (sub)class bar calls the method for foo after some calculations with callNextMethod().

Both methods have the same additional argument (with default) that should be passed to the method for foo, where only it is relevant.

setClass("foo", representation(x = "numeric"))
setClass("bar", contains = "foo")

setGeneric("foobar", function(object, ...) standardGeneric("foobar"))

setMethod("foobar", "foo", function(object, another.argument = FALSE, ...) {
    print(paste("in foo-method:", another.argument))
    if (another.argument) object@x^3
    else object@x^2
})

setMethod("foobar", "bar", function(object, another.argument = FALSE, ...) {
    print(paste("in bar-method:", another.argument))
     object@x <- sqrt(object@x)
    callNextMethod()
})

Problem description:
The arguments are not passed as expected, but the default values are taken from the method definition. Specifically, in the first method the argument is as specified in the call (TRUE), however, it changes to FALSE in the next method.

o1 <- new("bar", x = 4)

foobar(o1, another.argument = TRUE)

gives

[1] "in bar-method: TRUE"
[1] "in foo-method: FALSE"
[1] 4

I want the another.argument to be passed to the next method so that it is TRUE in the call to the foo method, too.


From ?callNextMethod I get that it should work as expected (i.e., the named argument is passed as it is in the call):

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.


My second question: How can I pass another.argument to the next method. (I would really like to keep default arguments in both methods)

Это было полезно?

Решение

I think this has to do with the way a method with a signature different from the generic is defined (within a function .local)

> selectMethod(foobar, "bar")
Method Definition:

function (object, ...) 
{
    .local <- function (object, another.argument = FALSE, ...) 
    {
        print(paste("in bar-method:", another.argument))
        object@x <- sqrt(object@x)
        callNextMethod()
    }
    .local(object, ...)
}

Signatures:
        object
target  "bar" 

defined "bar" 

The work-around is to either define the generic and methods to have the same signature

setGeneric("foobar",
    function(object, another.argument=FALSE, ...) standardGeneric("foobar"),
    signature="object")

or pass the arguments explicitly to callNextMethod

setMethod("foobar", "bar", function(object, another.argument = FALSE, ...) {
    print(paste("in bar-method:", another.argument))
     object@x <- sqrt(object@x)
    callNextMethod(object, another.argument, ...)
})
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top