R 中 R6 类的算术运算符重载

Arithmetic operators overload for R6classes in R

我正在开发自定义 R6Class,它将成为我的 R 包的主要结构。但问题是:

setMethod('+', signature("MyClass"), function(e1, e2)1)

setMethod('+', signature("R6"), function(e1, e2)1)

不工作因为当我 运行

a = MyClass$new()
a + a

我收到以下错误 Error in a + a : non-numeric argument to binary operator

我让它工作的唯一方法是这样的

`+.MyClass` = function(e1, e2) { return (1) }

但这没有用,因为未定义在空环境中从头开始加载包 (library(MyClass)) +.MyClass

那么,如何才能以正确的方式重载 R6 类 的运算符?

以防万一,片段:

MyClass = R6Class(
   "MyClass",
   public = list(
      initialize = function() {
      }
   ),
   private = list(
   )
)

setMethod('+', signature("MyClass"), function(e1, e2)1)
a = MyClass$new()
a+a

当您加载包时,+.MyClass 应该绝对可用,假设您已经导出函数。1

我可以用一个最小的例子来证明这一点,为此我使用了 devtools——我极力推荐使用 devtools 来创建包。首先,我创建一个最小的包结构:

devtools::create("dummypack", rstudio = FALSE)

然后我在 "dummypack/R/" 文件夹中添加一个 R 文件,"MyClass.R":

#' @export
MyClass = R6::R6Class(
    "MyClass",
    public = list(
        initialize = function() {
        }
    ),
    private = list(
    )
)

#' @export
`+.MyClass` = function(e1, e2) { return (1) }

此处的 #' @export 标签很关键;2 要使此功能可用,您需要的是 exported 在 "dummypack/NAMESPACE" 文件中(参见 Hadley Wickham 的 R 包的 the Namespaces chapter)。您需要您的 NAMESPACE 文件看起来像

export(MyClass)
export(`+.MyClass`)

确保同时导出 class 和重载的+ 运算符。或者你可以有一个像

这样的命名空间
exportPattern("^[^\.]")

导出不以 . 开头的所有内容(这是最初由 devtools::create() 生成的 NAMESPACE 文件)。因此,如果您 而不是 使用 devtools(和 Roxygen -- roxygen2),您需要自己编辑 NAMESPACE 文件以确保您的函数被导出。

那我运行

devtools::install("dummypack/")

在新的 R 会话中我 运行:

library(dummypack)
a = MyClass$new()
a+a
# [1] 1

表明您得到了想要的结果。


1 我原以为这个问题很容易被标记为重复。 This question 是我找到的最接近的,但似乎有点太 Roxygen-specific。

2 请注意,如果您使用 Roxygen(如果您使用 devtools::document(),这将起作用),这些标签仅对您的 NAMESPACE 文件有帮助。此外,对于我展示的最小示例,标签在技术上不是必需的,因为 devtools::create() 生成的默认名称空间只有上面讨论的 exportPattern("^[^\.]") 行。但是,在典型情况下,您需要这些标记,无论哪种方式,重要的是最终出现在 NAMESPACE 文件中的内容——您需要在 NAMESPACE 中显式 export() 语句或 exportPattern("^[^\.]").[= 之类的语句。 68=]