代码之家  ›  专栏  ›  技术社区  ›  Leonardo Lanchas

R中R6Class的算术运算符重载

  •  0
  • Leonardo Lanchas  · 技术社区  · 7 年前

    我正在定制 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
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   duckmayr    7 年前

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

    我可以用一个简单的例子来演示这一点,我使用了 devtools --我建议在创建包时使用devtools是不够的。首先,我创建一个最小的包结构:

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

    然后我在“dummypack/R/”文件夹MyClass.R中添加了一个R文件:

    #' @export
    MyClass = R6::R6Class(
        "MyClass",
        public = list(
            initialize = function() {
            }
        ),
        private = list(
        )
    )
    
    #' @export
    `+.MyClass` = function(e1, e2) { return (1) }
    

    这个 #' @export 这里的标签很重要; 2. 要使此功能可用,您需要的是 已导出 在“dummypack/NAMESPACE”文件中(请参见 the Namespaces chapter Hadley Wickham的R软件包)。您需要名称空间文件

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

    确保 二者都 类和重载 + 导出运算符。或者,您可以使用如下名称空间

    exportPattern("^[^\\.]")
    

    导出所有不是以 . (这是最初由生成的命名空间文件 devtools::create() )。所以,如果你是 使用 开发工具 (和Roxygen-- roxygen2 ),您需要自己编辑名称空间文件,以确保导出函数。

    然后我就跑

    devtools::install("dummypack/")
    

    在新的R会话中,我运行:

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

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


    1. 我原以为这个问题很容易被标记为重复问题。 This question 是我发现的最接近的,但似乎有点太过Roxygen特异性。

    2. 请注意,这些标记仅在使用Roxygen时对名称空间文件有帮助(如果使用 devtools::document() )。此外,对于我展示的最小示例,标记在技术上是不必要的,因为默认名称空间由 devtools::create() 刚刚接到电话 exportPattern("^[^\\.]") 如上所述。然而,在典型的情况下,您需要这些标记,无论哪种方式,重要的是名称空间文件中的最终内容——您需要显式的 export() 命名空间中的语句或 exportPattern(“^[^\.]”)