使用正式方法定义为S3对象调度S3样式

时间:2012-08-24 11:53:17

标签: r cran s4

this问题相关,但略有不同,希望更清楚。

我正在寻找一种 clean 方式来正式注册S4和S3类的方法,但不依赖于可怕的S3-dot-naming-scheme进行调度。一个例子:

setClass("foo");
setClass("bar");

setGeneric("test", function(x, ...){
    standardGeneric("test");
});

setMethod("test", "bar", function(x, ...){
    return("success (bar).");
});

obj1 <- 123;
class(obj1) <- "bar";
test(obj1);

此示例显示了如何为类test的S3对象注册bar方法,而无需将函数命名为test.bar,这很棒。但是,限制是如果我们以这种方式注册方法,它们将仅被分派到对象的第一个S3类。 E.g:

obj2 <- 123;
class(obj2) <- c("foo", "bar");
test(obj2);

这不起作用,因为S4方法调度只会尝试类foo及其超类。如果找不到test的适当方法,如何扩展此示例以便自动为bar选择foo方法?例如。 S3样式调度,但无需返回命名所有内容test.footest.bar

总结:如何创建一个使用形式方法调度的泛型函数,但另外还要回到具有多个类的S3对象的对象的第二,第三等类。

2 个答案:

答案 0 :(得分:3)

?setOldClass会给出答案:

setOldClass(c("foo", "bar"))

setGeneric("test", function(x, ...)standardGeneric("test"))
setMethod("test", "bar", function(x, ...)return("success (bar)."))

答案 1 :(得分:2)

你可以写一个方法

test = function(x, ...) UseMethod("test")

setGeneric("test")

.redispatch = function(x, ...)
{
    if (is.object(x) && !isS4(x) && length(class(x)) != 1L) {
        class(x) = class(x)[-1]
        callGeneric(x, ...)
    } else callNextMethod(x, ...)
}

setMethod(test, "ANY", .redispatch)

但我个人不会以这种方式混合S3和S4。