7

有没有办法定义当方法的参数丢失或 NULL时会发生什么?

在下面的示例中,无论我键入foo()还是,我都想调用相同的函数foo(NULL)。当然,我知道我可以有一个方法setMethod("foo","NULL",function(x) foo()) ,但那是代码复制和可能的错误来源。

谢谢!

setGeneric("foo",function(x) standardGeneric("foo"))
setMethod("foo","numeric",function(x) "numeric")
setMethod("foo","NULL",function(x) "NULL")
setMethod("foo","missing",function(x) "missing")

R> foo(1)
[1] "numeric"
R> foo()
[1] "missing"
R> foo(NULL)
[1] "NULL"
4

3 回答 3

13

派对迟到了将近三年,但你真的想要setClassUnion

> setClassUnion("missingOrNULL", c("missing", "NULL"))
> setGeneric("foo",function(x) standardGeneric("foo"))
> setMethod("foo","numeric",function(x) "numeric")
> setMethod("foo","missingOrNULL",function(x) "NULL")

> foo(1)
[1] "numeric"
> foo()
[1] "NULL"
> foo(NULL)
[1] "NULL"

setClassUnion创建一个虚拟类,它是组件类的超类(父类),因此两个子类都从该类继承,这意味着您可以对每个子类调度相同的函数。

于 2013-12-13T23:27:27.950 回答
3

UsingsetMethod("foo","NULL",function(x) foo())不是代码复制,因为您不复制代码而是调用它。我会说这是解决您的问题的好方法。

于 2010-12-14T15:11:27.027 回答
2

我想适当的方法是在签名中使用“ANY”:

setGeneric("foo",function(x) standardGeneric("foo"))
setMethod("foo","numeric",function(x) "numeric")
setMethod("foo","ANY",function(x) "ANY")

> foo(1)
[1] "numeric"

> foo()
[1] "ANY"

> foo(NULL)
[1] "ANY"

确保您指定了您想要处理的所有其他可能性,因为“ANY”还会处理所有不适合其他方法签名的其余部分。

如果您有可能缺少的参数,您可以不在 setMethods 的签名中指定它们并在泛型中设置默认值。在我看来,这是一个更好的设计选择。

setGeneric("foo",function(x,y=NULL,...) {
        standardGeneric("foo")
    })

setMethod("foo",c("numeric","ANY"),function(x,y,...) {
            print(y)
    })
setMethod("foo",c("numeric","numeric"),function(x,y,...) {
            x + y
    })

> foo(1)
NULL

> foo(1,3)
[1] 4

> foo(1,NULL)
NULL

现在您可以像处理缺少的参数一样处理代码中的 NULL 案例。

附注:现在我添加了 NULL 作为默认值,但在许多情况下,默认值有更明智的选择。请记住 setMethod 采用初始签名,并且当 y 设置为 NULL 时,这不会被默认替换。

例如:

setGeneric("bar",function(x,y=2,...) {
        standardGeneric("bar")
    })

setMethod("bar",c("numeric","ANY"),function(x,y,...) {
            x + y
    })
setMethod("bar",c("numeric","numeric"),function(x,y,...) {
            x - y
    })

> bar(1)
[1] 3

> bar(1,2)
[1] -1

> bar(1,NULL) # this y is not replaced with the default!
numeric(0)

肮脏的黑客:

我觉得这种方法有点尴尬,但这是一个肮脏的技巧,将所有缺少的参数设置为 NULL :

setGeneric("foo",function(x,y,z) {
    pars <- names(formals(foo))
    for(i in pars){
        tryerr <- try(get(i),silent=T)
        if(is(tryerr,"try-error")){ assign(i,NULL)}
    }
    standardGeneric("foo")
}

试试这个,你得到:

> foo(1)
[1] "numeric"

> foo(NULL)
[1] "NULL"

> foo()
[1] "NULL"

所以你再也不会派人去失踪了。你可以忘记它。但这不是适当的做事方式......

于 2010-12-15T12:39:25.987 回答