在R中,如何从一个包中扩展泛型方法?

时间:2015-07-09 12:21:36

标签: r generics packages

我有一个包含通用函数的包PackageA

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

        standardGeneric("doWork")
    })

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

        x == 10 # Some logic... 
    }

在依赖于PackageB的{​​{1}}中,我想向PackageA添加更多方法:

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") 中使用PackageA中的通用,但不需要加载PackageB来仅使用PackageA中的方法。

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:9)

这实际上是有记录的,但不是很清楚;请参阅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"。

答案 1 :(得分:4)

这似乎对我有用,但我没有看到它记录在案,所以我不一定认为它是犹太洁食。 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"))

主要技巧是从doWork中的pckgA导入并重新导出pckgB。然后从干净的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

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