Oop 在R中使用sd作为泛型函数
如果我有一个名为Oop 在R中使用sd作为泛型函数,oop,r,r-s3,Oop,R,R S3,如果我有一个名为foo的类,那么可以直接重载summary函数 summary.foo = function(x, ...) print("bar") 但是,此技术不适用于sd函数,即 > bar = createFooClass() > sd.foo = function(x, ...) print("Hi") > sd(bar) error: is.atomic(x) is not TRUE 重载此函数的正确方法是什么?查看sd()的代码——它有效地在内部分派。换句
foo
的类,那么可以直接重载summary
函数
summary.foo = function(x, ...) print("bar")
但是,此技术不适用于sd
函数,即
> bar = createFooClass()
> sd.foo = function(x, ...) print("Hi")
> sd(bar)
error: is.atomic(x) is not TRUE
重载此函数的正确方法是什么?查看
sd()
的代码——它有效地在内部分派。换句话说,它不是一个泛型函数,而是一个普通的旧正则函数
最简单的方法可能就是修改
sd()
以在类foo上分支 您需要为sd
定义一个新的泛型
最简单的方法是使用S4,因为它会自动处理默认的“sd”方法:
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
setClass(“foo”,list(a=“numeric”,name=“character”))
setGeneric(“sd”)
setMethod(“sd”、“foo”,
函数(x,na.rm=FALSE){
打印(“这是一个foo对象!”)
callNextMethod(x@a)
})
tf您可以劫持任何非泛型函数,将其设置为(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")
给予:
> args(sd.default)
function (x, na.rm = FALSE, ...)
NULL
> args(stats::sd)
function (x, na.rm = FALSE)
NULL
然后,这将提供所需的行为:
> bar <- 1:10
> sd(bar)
[1] 3.027650
> class(bar) <- "foo"
> sd(bar)
[1] "Hi"
>条形sd(条形)
[1] 3.027650
>等级(巴)标准差(巴)
[1] “嗨”
有趣的是,这在R扩展手册的编写部分有记录,我就是这么做的,但它似乎“错”了,而且有点尴尬。最好给R-devel发电子邮件,要求将sd
(或者更好的,var
)变成通用的。@hadley同意,但R Core需要维护这一点,在做一些通用的东西时,性能会受到影响,因此在R Ext.手册中有措辞和建议。我不相信这些借口。为什么说泛型而不是var?@hadley这不是我的借口;-)(我也同意你的看法)无论如何,在使用R Core之前,你会有点等待R Core实现它——因此“劫持”方法仍然是有价值的,直到R Core发布了一个稳定版本的Rsd()
作为一个泛型。很抱歉,我应该更清楚地表达我的意见-有时,在R-core实施明确需要的更改之前,您需要给他们一段艰难的时间。
> bar <- 1:10
> sd(bar)
[1] 3.027650
> class(bar) <- "foo"
> sd(bar)
[1] "Hi"