If I a have a class called foo
, then it is straightforward to overload the summary
function
summary.foo = function(x, ...) print("bar")
However this technique does not work with the sd
function, that is
> bar = createFooClass()
> sd.foo = function(x, ...) print("Hi")
> sd(bar)
error: is.atomic(x) is not TRUE
What is the correct way of overloading this function?
You can hijack any non-generic function, make it (S3) generic and set the original version to be the default version. For example:
## 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")
A final step, if this is in a package, is to add a ...
argument to sd.default
to allow passing of package checks:
formals(sd.default) <- c(formals(sd.default), alist(... = ))
giving:
> args(sd.default)
function (x, na.rm = FALSE, ...)
NULL
> args(stats::sd)
function (x, na.rm = FALSE)
NULL
This then gives the desired behaviour:
> bar <- 1:10
> sd(bar)
[1] 3.027650
> class(bar) <- "foo"
> sd(bar)
[1] "Hi"
This is documented in section 7.1 of the Writing R Extensions manual
You need to define a new generic for sd
.
The easiest way is to use S4, because it handles the default "sd" method automatically:
setClass("foo", list(a = "numeric", names = "character"))
setGeneric("sd")
setMethod("sd", "foo",
function(x, na.rm = FALSE){
print("This is a foo object!")
callNextMethod(x@a)
})
tf <- new("foo", a = 1:10)
sd(tf)
#[1] "This is a foo object!"
#[1] 3.027650
Look at the code of sd()
---it effectively dispatches internally. In other words, it is not a generic function but a plain old regular function.
The easiest may just be to modify sd()
to branch on class foo.
来源:https://stackoverflow.com/questions/4728342/using-sd-as-a-generic-function-in-r