2011-01-18 10 views
8

Gdybym dysponowanie klasy o nazwie foo, to jest proste przeciążyć funkcję summaryKorzystanie sd jako rodzajowy funkcji w R

summary.foo = function(x, ...) print("bar") 

Jednak technika ta nie działa z funkcji sd, to

> bar = createFooClass() 
> sd.foo = function(x, ...) print("Hi") 
> sd(bar) 
    error: is.atomic(x) is not TRUE 

Jaki jest prawidłowy sposób przeciążenia tej funkcji?

Odpowiedz

7

można przejąć żadnej funkcji non-generic, sprawiają, że (S3) rodzajowy i ustawić oryginalną wersję być domyślną wersją. Na przykład:

## make an S3 generic for sd 
sd <- function(x, ...) UseMethod("sd") 
## take the usual definition of sd, 
## and set it to be the default method 
sd.default <- stats::sd 
## create a method for our class "foo" 
sd.foo = function(x, ...) print("Hi") 

Ostatnim krokiem, jeśli ten znajduje się w opakowaniu, jest dodanie ... argument sd.default aby umożliwić przekazywanie kontroli pakietów:

formals(sd.default) <- c(formals(sd.default), alist(... =)) 

podając:

> args(sd.default) 
function (x, na.rm = FALSE, ...) 
NULL 
> args(stats::sd) 
function (x, na.rm = FALSE) 
NULL 

To daje pożądane zachowanie:

> bar <- 1:10 
> sd(bar) 
[1] 3.027650 
> class(bar) <- "foo" 
> sd(bar) 
[1] "Hi" 

Jest to udokumentowane w section 7.1 rozszerzeń Pisanie R ręcznych

+0

Lepiej wysłać na adres R-devel i zażądać, aby 'sd' (lub lepiej,' var') było generyczne. – hadley

+0

@hadley zgodził się, ale tak samo jak potrzeba R Core do utrzymania tego, istnieje uderzenie wydajności podczas robienia czegoś generycznego, stąd też sformułowania i porady w R Ext. Podręcznik. –

+0

Nie kupuję tych wymówek. Dlaczego ma znaczyć rodzajowy, a nie var? – hadley

1

Sprawdź kod sd() --- skutecznie wysyła wewnątrz. Innymi słowy, nie jest to funkcja ogólna, lecz zwykła stara funkcja regularna.

Najprostszym może być zmodyfikowanie oddziału na klasę foo na sd().

+0

Zabawne, że to, co zrobiłem, ale to po prostu wydawało się „źle” i nieco kłopotliwe. – csgillespie

3

Musisz zdefiniować nowy rodzaj dla sd.

Najprostszym sposobem jest użycie S4, ponieważ obsługuje on domyślnym „sd” metoda automatycznie:

setClass("foo", list(a = "numeric", names = "character")) 

setGeneric("sd") 

setMethod("sd", "foo", 
      function(x, na.rm = FALSE){ 
       print("This is a foo object!") 
       callNextMethod([email protected]) 
       }) 

tf <- new("foo", a = 1:10) 
sd(tf) 
#[1] "This is a foo object!" 
#[1] 3.027650 
Powiązane problemy