使用sd作为R中的通用函数

csg*_*pie 8 oop r r-s3

如果我有一个被调用的类foo,那么重载该summary函数是很简单的

summary.foo = function(x, ...) print("bar")
Run Code Online (Sandbox Code Playgroud)

但是,这种技术不适用于该sd功能

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

重载此功能的正确方法是什么?

Rei*_*son 7

您可以劫持任何非泛型函数,使其(S3)通用并将原始版本设置为默认版本.例如:

## 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")
Run Code Online (Sandbox Code Playgroud)

最后一步,如果它在一个包中,是添加一个...参数sd.default以允许传递包检查:

formals(sd.default) <- c(formals(sd.default), alist(... = ))
Run Code Online (Sandbox Code Playgroud)

赠送:

> args(sd.default)
function (x, na.rm = FALSE, ...) 
NULL
> args(stats::sd)
function (x, na.rm = FALSE) 
NULL
Run Code Online (Sandbox Code Playgroud)

然后,这会产生所需的行为:

> bar <- 1:10
> sd(bar)
[1] 3.027650
> class(bar) <- "foo"
> sd(bar)
[1] "Hi"
Run Code Online (Sandbox Code Playgroud)

这在Writing R Extensions手册的第7.1节中有记录