如何使用S3方法处理S4对象?

时间:2011-05-06 14:47:27

标签: oop r r-s3 r-s4

我正在编写一个S3方法,我想使用任何 R对象,包括S4对象。

我不明白的第一件事是S4类似乎不是从S4基类派生的,所以给定f <- function(x) UseMethod("f")我不能只声明f.S4调度方法并且有它拾取所有S4对象。 (虽然如果unclass是一个S4对象,它似乎确实被赋予了类S4。)我应该如何管理调度?

似乎处理这些S4对象的最简单方法是将它们转换为列表。不幸的是,as.list会抛出一个错误(“没有方法可以将这个S4类强制转换为向量”)。

这是我的测试S4对象:

library(gWidgetstcltk)
win <- gwindow()

S3Part包中的函数S3Classmethods看起来很有希望,但是当我在win上使用它们时,它们都会抛出错误。因此,问题2是:是否有将S4对象转换为列表的一般方法?

1 个答案:

答案 0 :(得分:6)

S4是一个超类(虚拟类,无论如何,有人请用正确的名称编写),不能直接调度使用。顺便说一下S3也一样。您可以像对S3类一样对S4类进行S3调度。在旁注中,如果未指定任何内容,则在S4对象上调用myfun将导致.default函数。 :

myfun <- function(object, ...) UseMethod("myfun")

myfun.default <- function(object,...){
    cat("default method.\n")
    print(object)
}

myfun.gWindow <- function(object,...){
    cat("Here here...")
    print(object)
}

x <- 1:10
myfun(x)
myfun(win)
rm(myfun.gWindow)
myfun(win)

如果要捕获所有S4方法,可以使用isS4()在.default函数或泛型函数中手动分派。在.default函数中添加调度允许自动S3调度到某些S4类。如果你在通用中添加它,你只需要发送到所有S4无关紧要的内容:

    myfun.default <- function(object,...){
        if(isS4(object)) myfun.S4(object,...)
        else {
          cat("default method.\n")
          print(object)
        }
    }

    myfun.S4 <- function(object,...){
        cat("S4 method\n")
        print(object)
    }

x <- 1:10
myfun(x)
myfun(win)

关于你的第二个问题:gWindow是一个特例。尝试使用str(win)时,它也会返回错误。我不知道确切的结构,但它绝对不是一个普通的S4对象。