如何覆盖 R 中非泛型函数的实现
How to override the implementation of a non-generic function in R
在 R 中,我有一个模拟一维向量的 S3 class,因此我想实现 mean
、sum
、max
的自定义版本,等等。假设它看起来像这样:
my_class = function(){
structure(list(), class='my_class')
}
如果我定义 mean.my_class
etc:
,以上所有方法都可以正常工作
mean.my_class = function(x){
2
}
mean(my_class())
但是,我也想对 var
这样的函数执行此操作,这不是通用方法。如果我创建这样一个函数,然后在 class:
的实例上调用 var
var.my_class = function(his){
# Do stuff here
}
var(my_class())
我收到错误:
Error in var(my_class()) : is.atomic(x) is not TRUE
这是因为没有通用的 var
函数,它只是在我的结构上调用 stats::var
。如果没有通用方法,我如何提供自定义实现?我也不想破坏常规向量的 var
方法。
从methods for non generics开始,S4
setMethod
似乎与S3
兼容 class:
setMethod("var","my_class",function(x, y = NULL, na.rm = FALSE, use) {"Var for my_class"})
#> Creating a generic function for 'var' from package 'stats' in the global environment
#> in method for 'var' with signature '"my_class"': no definition for class "my_class"
my_class = function(){
structure(list(), class='my_class')
}
var(my_class())
#> [1] "Var for my_class"
var(1:10)
#> [1] 9.166667
您可以使用与现有非泛型函数相同的名称和签名来创建自己的泛型:
var = function (x, y = NULL, na.rm = FALSE, use) UseMethod('var')
var.my_class = function (x, y, na.rm, use) 42
registerS3method('var', 'default', stats::var)
registerS3method('var', 'my_class', var.my_class)
... 而不是手动复制泛型函数的形式参数列表,您可以使用以下内容自动生成它:
var = function () UseMethod('var')
formals(var) = formals(stats::var)
— 当然,以上仅在调用者调用 您的 var
函数时有效。例如,如果有人调用 stats::var
,您的泛型将找不到,因此不会发生 S3 方法分派。
请注意,R 3.5 改变了 S3 方法查找跨环境的工作方式,仅仅定义一个适当命名的函数不再足以从不同的环境中找到该方法——您 需要 调用 registerS3method
(不仅适用于像 var
这样的新泛型,也适用于您的 mean
!)。不幸的是,这个函数几乎没有官方文档,只有一些 blog posts by Kurt Hornik.
在 R 中,我有一个模拟一维向量的 S3 class,因此我想实现 mean
、sum
、max
的自定义版本,等等。假设它看起来像这样:
my_class = function(){
structure(list(), class='my_class')
}
如果我定义 mean.my_class
etc:
mean.my_class = function(x){
2
}
mean(my_class())
但是,我也想对 var
这样的函数执行此操作,这不是通用方法。如果我创建这样一个函数,然后在 class:
var
var.my_class = function(his){
# Do stuff here
}
var(my_class())
我收到错误:
Error in var(my_class()) : is.atomic(x) is not TRUE
这是因为没有通用的 var
函数,它只是在我的结构上调用 stats::var
。如果没有通用方法,我如何提供自定义实现?我也不想破坏常规向量的 var
方法。
从methods for non generics开始,S4
setMethod
似乎与S3
兼容 class:
setMethod("var","my_class",function(x, y = NULL, na.rm = FALSE, use) {"Var for my_class"})
#> Creating a generic function for 'var' from package 'stats' in the global environment
#> in method for 'var' with signature '"my_class"': no definition for class "my_class"
my_class = function(){
structure(list(), class='my_class')
}
var(my_class())
#> [1] "Var for my_class"
var(1:10)
#> [1] 9.166667
您可以使用与现有非泛型函数相同的名称和签名来创建自己的泛型:
var = function (x, y = NULL, na.rm = FALSE, use) UseMethod('var')
var.my_class = function (x, y, na.rm, use) 42
registerS3method('var', 'default', stats::var)
registerS3method('var', 'my_class', var.my_class)
... 而不是手动复制泛型函数的形式参数列表,您可以使用以下内容自动生成它:
var = function () UseMethod('var')
formals(var) = formals(stats::var)
— 当然,以上仅在调用者调用 您的 var
函数时有效。例如,如果有人调用 stats::var
,您的泛型将找不到,因此不会发生 S3 方法分派。
请注意,R 3.5 改变了 S3 方法查找跨环境的工作方式,仅仅定义一个适当命名的函数不再足以从不同的环境中找到该方法——您 需要 调用 registerS3method
(不仅适用于像 var
这样的新泛型,也适用于您的 mean
!)。不幸的是,这个函数几乎没有官方文档,只有一些 blog posts by Kurt Hornik.