S4 Классы: несколько типов на каждый слот

Можно ли создать класс S4, где один или несколько слотов могут быть нескольких классов? Например. Скажем, что у вас была ситуация, когда данные могут быть либо вектором, либо data.frame.

exampleClass <- setClass("exampleClass",
    representation(raw=c("data.frame","numeric","character"),
    anotherSlot=c("data.frame","numeric")) 

Или это тип ситуации, когда определение подкласса/суперкласса становится необходимым?

PS: Поиск полезного учебника по классам S4 дает ограниченные результаты. Было бы полезно получить ссылки на хороший учебник по созданию/использованию/документации класса S4.

Ответы

Ответ 1

R имеет "классовые союзы", поэтому

setOldClass("data.frame")
setClassUnion("data.frameORvector", c("data.frame", "vector"))

Класс data.frameORvector является виртуальным, поэтому он не может быть создан, но может использоваться в других слотах (representation=) в качестве содержащегося класса (contains=) и для отправки

A = setClass("A", 
        representation=representation(x="data.frameORvector"))


> A(x=1:3)
An object of class "A"
Slot "x":
[1] 1 2 3

> A(x=data.frame(x=1:3, y=3:1))
An object of class "A"
Slot "x":
  x y
1 1 3
2 2 2
3 3 1

Методы могут быть сложными для реализации, потому что все, что вам известно, состоит в том, что слот содержит один из родительских типов объединения классов.

setGeneric("hasa", function(object) standardGeneric("hasa"))
setMethod("hasa", "data.frameORvector", function(object) typeof([email protected]))

> hasa(A(x=1:5))
[1] "integer"
> hasa(A(x=data.frame(y=1:5)))
[1] "list"

Я действительно нахожу документацию на ?Classes, ?Methods, ?setClass и друзья полезны. У Hadley Wickham есть учебник (пример на этой странице не так уж и силен, он создает экземпляр Person, тогда как концептуально писать People для использования сильных сторон вектора прочности), и в этом недавнем курсе Bioconductor есть раздел. Я не думаю, что он подробно обсуждает классовые союзы.