簡體   English   中英

如何在 R 中覆蓋非泛型 function 的實現

[英]How to override the implementation of a non-generic function in R

在 R 中,我有一個模擬一維向量的 S3 class,所以我想實現meansummax等的自定義版本。假設它看起來像這樣:

my_class = function(){
  structure(list(), class='my_class')
}

如果我定義mean.my_class等,上述所有方法都可以正常工作:

mean.my_class = function(x){
  2
}

mean(my_class())

但是,我也想對var之類的函數執行此操作,這不是通用方法。 如果我創建這樣一個 function,然后在我的 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 function,它只是在我的結構上調用stats::var 如果沒有通用方法,我如何提供自定義實現? 我也不想破壞常規向量的var方法。

您可以使用與現有非泛型 function 相同的名稱和簽名創建自己的泛型:

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)

…而不是手動復制通用 function 的形式參數列表,您可以使用以下命令自動生成它:

var = function () UseMethod('var')
formals(var) = formals(stats::var)

— 當然,上述方法僅在調用者調用您的var function 時才有效。 如果有人調用例如stats::var ,將找不到您的泛型,因此不會發生 S3 方法調度。


Beware that R 3.5 changed the way S3 method lookup works across environments, and merely defining an appropriately-named function is no longer sufficient for the method to be found from a different environment — you need to invoke registerS3method (not just for new generics like var但也是為了你的mean 。),不幸的是,這個函數幾乎沒有官方文檔,只有Kurt Hornik 的一些博客文章

非 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM