【问题标题】:In R, how can I extend generic methods from one package in another?在 R 中,如何从另一个包中的一个包扩展泛型方法?
【发布时间】:2015-09-27 19:42:54
【问题描述】:

我有一个带有通用功能的包PackageA

#' doWork
#' 
#' Do some work!
#'
#' @export
setGeneric(
    "doWork", 
    function(x) {

        standardGeneric("doWork")
    })

setMethod(
    "doWork", 
    signature = c("numeric"), 
    definition = function(x) {

        x == 10 # Some logic... 
    }

在依赖PackageAPackageB中,我想给doWork添加更多方法:

#' @import PackageA
setMethod(
    "doWork", 
    signature = c("character"), 
    definition = function(x) {

        length(x) == 1 && x == "10" # Some more logic... 
    }

这行得通。但是,这意味着PackageB的用户也必须library(PackageA)

这失败了:

library(PackageB)

doWork("10") # Fails!

这行得通:

library(PackageA)
library(PackageB)

doWork("10")

我想在PackageB 中使用来自PackageA 的泛型,但不需要加载PackageA 以仅使用PackageB 中的方法。

我怎样才能做到这一点?

【问题讨论】:

    标签: r generics packages


    【解决方案1】:

    这实际上是有记录的,但不是很清楚;请参阅Writing R Extensions1.5.6 部分。

    诀窍是从PackageA 导入泛型,然后从PackageB 重新导出它。使用 roxygen 注释,这看起来像:

    #' @importMethodsFrom PackageA doWork
    #' @export 
    setMethod(
        "doWork", 
        signature = c("character"), 
        definition = function(x) {
    
            length(x) == 1 && x == "10" # Some more logic... 
        })
    

    当您调用devtools::document() 时,这将失败,除非您首先加载PackageA(调用library(PackageA))。

    但是,一旦构建,PackageA 就不是必需的了:

    > library(PackageB)
    > showMethods("doWork")
    Function: doWork (package PackageA)
    x="character"
    x="numeric"
    

    作为参考,自动生成的NAMESPACE 文件如下所示:

    exportMethods(doWork)
    importMethodsFrom(PackageA, doWork)
    

    此方法不会产生有关命名冲突等的警告,因此它似乎是“kosher”。

    【讨论】:

    • 这个答案对我有用,并且符合 R 扩展手册。
    【解决方案2】:

    这似乎对我有用,但我没有看到它记录在案,所以我不一定认为它是犹太洁食。 pckgA:

    #' @export
    
    setGeneric("doWork", function(x) standardGeneric("doWork"))
    setMethod("doWork", signature = "numeric", function(x) x == 11)
    

    pckgB:

    #' @export
    #' @import pckgA
    
    setGeneric("doWork", getGeneric("doWork", package="pckgA"))
    setMethod("doWork", "character", function(x) identical(x, "10"))
    

    主要技巧是在pckgB 中从pckgA 导入和重新导出doWork。然后从一个干净的 R 会话开始:

    library(pckgB)
    doWork("10")
    # [1] TRUE
    doWork("11")
    # [1] FALSE
    doWork(11)
    # [1] TRUE
    library(pckgA)
    doWork(11)
    # [1] TRUE
    doWork("10")
    # [1] TRUE
    

    您可能需要完全清除您的工作区(包括隐藏对象)以摆脱任何先前的方法定义才能真正正常生效。

    【讨论】:

    • 我的 roxygen 似乎不喜欢这样:“roxygen 块失败......。数据不是课堂环境中的插槽”
    • 我会标记这是解决方案,因为它有效,但它似乎不是正确的方法。
    猜你喜欢
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 2021-10-09
    • 2015-08-23
    • 2014-02-23
    相关资源
    最近更新 更多