有没有办法定义当方法的参数缺失或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"
答案 0 :(得分:12)
派对迟到差不多三年,但你真的想要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
创建一个虚拟类,它是组件类的超类(父类),因此两个子类都从该类继承,这意味着您可以针对每个子类调度相同的函数。
答案 1 :(得分:3)
使用setMethod("foo","NULL",function(x) foo())
不是代码复制,因为您不复制代码而是调用代码。我会说这是一个解决问题的好方法。
答案 2 :(得分: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)
DIRTY HACK:
我觉得这个方法有点尴尬,但这里有一个脏的黑客将所有缺少的参数设置为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"
所以你再也不会派遣失踪者了。你可以忘掉它。但这不是做事的恰当方式......