Объединение методов S4 и S3 в одной функции

Каков хороший способ определения функции общего назначения, которая должна иметь реализации для классов S3 и S4? Я использовал что-то вроде этого:

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

setMethod("myfun", "ANY", function(x, ...) {
    if(!isS4(x)) {
        return(UseMethod("myfun"));
    }
    stop("No implementation found for class: ", class(x));
});

Это успешно:

myfun.bar <- function(x, ...){
    return("Object of class bar successfully dispatched.");
}
object <- structure(123, class=c("foo", "bar"));
myfun(object)

Есть ли ход "родной" способ сделать это? Я знаю, что мы можем определить методы S4 для классов S3, используя setOldClassоднако таким образом мы теряем диспетчеризацию метода S3 в случае, если у объекта есть несколько классов. Например (в чистом сеансе):

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

setOldClass("bar")
setMethod("myfun", "bar", function(x, ...){
    return("Object of class bar successfully dispatched.");
});

object <- structure(123, class=c("foo", "bar"));
myfun(object)

Это не удается, потому что второй класс object, в этом случае bar, игнорируется. Возможно, мы могли бы это исправить, определив формальное наследование S4 между foo а также bar, но для моего приложения я бы предпочел myfun.bar работать из коробки на объектах S3 с классом bar,

В любом случае, все становится грязно, и я думаю, что это общая проблема, так что, возможно, есть лучшие способы сделать это?

1 ответ

Решение

В разделе "Методы универсальных функций S3" раздела "Методы" предлагается универсальный S3, метод стиля S3 для классов S4 и сам метод S4.

setClass("A")                    # define a class

f3 <- function(x, ...)           # S3 generic, for S3 dispatch    
    UseMethod("f3")
setGeneric("f3")                 # S4 generic, for S4 dispatch, default is S3 generic
f3.A <- function(x, ...) {}      # S3 method for S4 class
setMethod("f3", "A", f3.A)       # S4 method for S4 class

Универсальный S3 необходим для отправки классов S3.

SetGeneric() устанавливает f3 (т. Е. Универсальный S3) в качестве значения по умолчанию, а f3, ЛЮБОЙ метод на самом деле является универсальным S3. Так как "ЛЮБОЙ" находится (в некотором роде) в корне иерархии классов, любой объект (например, объекты S3), для которого метод S4 не существует, попадает в общий S3.

Определение универсального S3 для класса S4 описано на странице справки "Методы". Я думаю, примерно, что S3 не знает о методах S4, поэтому, если кто-то вызывает универсальный S3 (например, потому что он находится в пространстве имен пакета, где пакет знает о S3 f3, но не S4 f3), универсальный f3 не нашел бы метод S4. Я всего лишь посланник.

Другие вопросы по тегам