2012-08-23 12 views
9

Quale è un buon modo per definire una funzione generica che dovrebbe avere implementazioni per entrambe le classi S3 e S4? Sono stato con qualcosa di simile:Combinazione dei metodi S4 e S3 in una singola funzione

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)); 
}); 

Questo succede:

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

C'è una mossa modo "nativo" per raggiungere questo obiettivo? So che possiamo definire i metodi S4 per le classi S3 usando setOldClass, tuttavia in questo modo perdiamo il dispacciamento del metodo S3 nel caso in cui un oggetto abbia più classi. Per esempio. (In una sessione pulita):

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) 

Ciò non riesce perché la seconda classe di object, in questo caso bar, viene ignorato. Probabilmente potremmo risolvere questo problema definendo l'ereditarietà S4 formale tra foo e bar, ma per la mia applicazione preferirei che lo myfun.bar funzioni fuori dagli schemi sugli oggetti S3 con una classe bar.

In entrambi i casi, le cose stanno diventando disordinate, e immagino che questo sia un problema comune, quindi ci sono probabilmente modi migliori per farlo?

+0

Vedere anche http://stackoverflow.com/questions/12709933/adding-s4-dispatch-to-base-r-s3-generic per il caso speciale di aggiunta di S4 a un S3 generico nella base R. –

risposta

13

La sezione "Metodi per le funzioni generiche S3" dei metodi "suggerisce" un metodo S3 generico, un metodo in stile S3 per le classi S4 e il metodo S4 stesso.

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 

Il generico S3 è necessario per inviare classi S3.

Il setGeneric() imposta f3 (cioè S3 generico) come predefinito e f3, il metodo ANY è in realtà S3 generico. Poiché "ANY" è (sorta) la radice della gerarchia delle classi, qualsiasi oggetto (ad es. Oggetti S3) per il quale non esiste un metodo S4 finisce sul generico S3.

La definizione di un S3 generico per una classe S4 è descritta nella pagina della Guida? Metodi. Penso che, approssimativamente, S3 non conosca i metodi S4, quindi se si invoca il generico S3 (ad esempio, perché uno è in uno spazio nome del pacchetto in cui il pacchetto conosce l'S3 f3 ma non l'S4 f3) il generico f3 non troverebbe il metodo S4. Sono solo il messaggero.

+0

Quindi vuol dire che i metodi S4 vengono cercati prima sulla base delle loro firme e in mancanza di una corrispondenza, i metodi S3 vengono quindi inviati? –

+0

@DWin sì giusto –

+0

Potresti elaborare il motivo per cui sono necessarie la prima e l'ultima riga? – Jeroen

Problemi correlati