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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With