Объединение методов 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. Я всего лишь посланник.