2012-06-09 13 views

Odpowiedz

33

Discover rodzajową tak, że wiemy jakie są nasze cele

> getGeneric("[") 
standardGeneric for "[" defined from package "base" 

function (x, i, j, ..., drop = TRUE) 
standardGeneric("[", .Primitive("[")) 
<bytecode: 0x32e25c8> 
<environment: 0x32d7a50> 
Methods may be defined for arguments: x, i, j, drop 
Use showMethods("[") for currently available ones. 

Zdefiniuj prostą klasę

setClass("A", representation=representation(slt="numeric")) 

i wdraża metodę

setMethod("[", c("A", "integer", "missing", "ANY"), 
    ## we won't support subsetting on j; dispatching on 'drop' doesn't 
    ## make sense (to me), so in rebellion we'll quietly ignore it. 
    function(x, i, j, ..., drop=TRUE) 
{ 
    ## less clever: update slot, return instance 
    ## [email protected] = [email protected][i] 
    ## x 
    ## clever: by default initialize is a copy constructor, too 
    initialize(x, [email protected][i]) 
}) 

w akcji:

> a = new("A", slt=1:5) 
> a[3:1] 
An object of class "A" 
Slot "slt": 
[1] 3 2 1 

Istnieją różne strategie do obsługi (niejawnie) wielu sygnatur, na przykład prawdopodobnie chcesz również obsługiwać wartości logiczne i wartości indeksu, prawdopodobnie zarówno dla i i j. Najprostszym jest wzór "elewacji", w którym każda metoda dokonuje wstępnego przymusu do wspólnego indeksu podzbioru, np. integer, aby umożliwić ponowne zamówienie i powtórzenie wpisów indeksu, a następnie wykorzystuje callGeneric do wywołania pojedynczej metody to działa na podzbiór klasy.

Nie ma żadnych różnic koncepcyjnych dla [[, poza tym, że chce szanować semantykę zwracania treści, a nie inną instancję obiektu, co sugeruje [. Dla $ mamy

> getGeneric("$") 
standardGeneric for "$" defined from package "base" 

function (x, name) 
standardGeneric("$", .Primitive("$")) 
<bytecode: 0x31fce40> 
<environment: 0x31f12b8> 
Methods may be defined for arguments: x 
Use showMethods("$") for currently available ones. 

i

setMethod("$", "A", 
    function(x, name) 
{ 
    ## 'name' is a character(1) 
    slot(x, name) 
}) 

z

> a$slt 
[1] 1 2 3 4 5 
+7

Dzięki Martin! Jest to bardzo pomocne (do tego stopnia, że ​​naruszam zasadę "nie zostawiajcie podziękowań, ponieważ to jest hałas" :-) –

7

chciałbym zrobić jak @Martin_Morgan sugerowane dla operatorów pan wspomniał. Dodałbym jednak kilka punktów:

1) Byłbym ostrożny w definiowaniu operatora $, aby uzyskać dostęp do slotu S4 (chyba że zamierzasz uzyskać dostęp do kolumny z ramki danych, która jest przechowywana w konkretnym gnieździe?) . Ogólną sugestią jest napisanie funkcji akcesora, takich jak getMySlot() i setMySlot(), aby uzyskać potrzebne informacje. Możesz użyć operatora @, aby uzyskać dostęp do danych z tych gniazd, chociaż ustawienie get i set są najlepsze jako interfejs użytkownika. Używanie $ może być mylące dla użytkownika, który prawdopodobnie oczekiwałby danych.frame. Poradnik na ten temat znajduje się w samouczku Christophe'a Genoliniego z this S4. Jeśli to nie jest sposób, w jaki zamierzałeś użyć $, zignoruj ​​moją sugestię (ale samouczek wciąż jest świetnym źródłem!).

2) Jeśli definiujesz [ i [[ dziedziczyć z innej klasy, jak wektor, chcemy też, aby określić el() (Odpowiednik [][[1L]] lub pierwszego elementu z podzbioru []) i length(). Obecnie piszę klasę, która dziedziczy po numerycznej, a metody numeryczne automatycznie spróbują użyć tych funkcji ze swojej klasy. Jeśli zajęcia są dla bardziej ograniczonego lub osobistego użytku, nie może to stanowić problemu.

Przepraszam, zostawiłbym to jako komentarz, ale jestem nowy w SO i nie mam jeszcze rep!

Powiązane problemy