将参数的默认值从S4泛型函数调度到其关联的方法

Rap*_*ter 8 methods r default-value s4

假设与特定S4泛型函数/方法关联的所有 S4方法共享一个应该具有特定默认值的形式参数.直觉上,我会在S4 泛型的定义中陈述这样一个论点(而不是在每个方法定义中陈述它对我来说似乎有点多余).

但是,我注意到这种方式我遇到了麻烦,因为似乎没有将形式参数的默认值分派给方法,因此抛出了错误.

这有点不符合通用和方法相结合的想法吗?当默认值始终相同时,为什么我必须再次分别在每个方法中声明形式参数?我可以以某种方式明确地发送正式参数的默认值吗?


您可以在下面找到该行为的简短说明

通用功能

setGeneric(
    name="testFoo",
    signature=c("x", "y"),
    def=function(
        x,
        y,
        do.both=FALSE,
        ...
    ) {
    standardGeneric("testFoo")       
    }
)
Run Code Online (Sandbox Code Playgroud)

方法

setMethod(
    f="testFoo", 
    signature=signature(x="numeric", y="numeric"),
    definition=function(
        x,
        y
    ) { 
    if (do.both) {
        out <- list(x=x, y=y)
    } else {
        out <- x
    }
    return(out)
    }
)
Run Code Online (Sandbox Code Playgroud)

错误

> testFoo(x=1, y=2)
Error in .local(x, y, ...) : object 'do.both' not found
Run Code Online (Sandbox Code Playgroud)

冗余声明do.both修复它

setMethod(
    f="testFoo", 
    signature=signature(x="numeric", y="numeric"),
    definition=function(
        x,
        y,
        do.both=FALSE
    ) { 
    if (do.both) {
        out <- list(x=x, y=y)
    } else {
        out <- x
    }
    return(out)
    }
)

> testFoo(x=1, y=2)
[1] 1
Run Code Online (Sandbox Code Playgroud)

Jos*_*ien 9

当你调用时testFoo(x=1, y=2),它首先由S4泛型处理,它寻找一个方法,找到它,并向它发送一个看起来像这样的调用:testFoo(x=1, y=2, do.both=FALSE, ...).

用下面的话说?standardGeneric:

'standardGeneric'使用调用它的帧中的实际参数调度为名为'f'的泛型函数定义的方法.

如果该方法与它分派该呼叫不采取一个do.both参数,方法--- 就像任何其它的R功能 ---抛出一个错误.没有函数可以处理包含参数的调用,foo除非它的函数定义包含(a)形式参数foo或(b)"dots"参数...,它可以吸收任意提供的参数.

基本上你所尝试的与以下内容没有什么不同,后者以类似但可能更容易看到的方式失败:

testFooGeneric <- function(x=1, y=2, do.both=FALSE, ...) {
    ## The line below does essentially what standardGeneric() does
    if(is.numeric(x) & is.numeric(y)) {
        testFooMethod(x=x, y=y, do.both=do.both)
    }
}

testFooMethod <- function(x, y) {
    cat("Success!\n")
}

testFooGeneric(x=1, y=2)
# Error in testFooMethod(x = x, y = y, do.both = do.both) : 
#   unused argument(s) (do.both = do.both)
Run Code Online (Sandbox Code Playgroud)

要解决上述问题,您需要testFooMethod()使用以下两种方法之一重新定义,其中任何一种方法都可以修复您的S4方法:

## Option 1
testFooMethod <- function(x, y, do.both) {
    cat("Success!\n")
}
testFooGeneric(x=1, y=2)
# Success!

## Option 2
testFooMethod <- function(x, y, ...) {
    cat("Success!\n")
}
testFooGeneric(x=1, y=2)
## Success!
Run Code Online (Sandbox Code Playgroud)