7

这个问题有关,但略有不同,希望更清楚。

我正在寻找一种干净的方式来正式注册 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 类。例如:

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

这不起作用,因为 S4 方法分派只会尝试类foo及其超类。如何扩展此示例,以便在找不到合适的方法时自动选择test方法?例如 S3 风格的调度,但不必重新命名所有内容和?barfootest.footest.bar

总而言之:如何创建一个使用正式方法分派的通用函数,但对于具有多个类的 S3 对象,还依赖于对象的第二个、第三个等类。

4

2 回答 2

3

?setOldClass将给出答案:

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

setGeneric("test", function(x, ...)standardGeneric("test"))
setMethod("test", "bar", function(x, ...)return("success (bar)."))
于 2012-08-24T16:19:13.523 回答
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。

于 2012-08-25T12:14:13.247 回答