在 R 中,如何将一个包中的泛型方法扩展到另一个包中?
In R, how can I extend generic methods from one package in another?
我有一个具有通用功能的包 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
中,它依赖于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")
我想在 PackageB
中使用 PackageA
中的泛型,但不需要加载 PackageA
以仅使用 PackageB
中的方法。
我怎样才能做到这一点?
这似乎对我有用,但我没有看到它的记录,所以我不一定认为它是犹太洁食。 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
您可能需要完全清除您的工作区(包括隐藏的对象)以摆脱任何先前的方法定义,这样才能真正正常生效。
这个其实是有文档记录的,但是不是很清楚;请参阅 Writing R Extensions 的 1.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"。
我有一个具有通用功能的包 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
中,它依赖于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")
我想在 PackageB
中使用 PackageA
中的泛型,但不需要加载 PackageA
以仅使用 PackageB
中的方法。
我怎样才能做到这一点?
这似乎对我有用,但我没有看到它的记录,所以我不一定认为它是犹太洁食。 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
您可能需要完全清除您的工作区(包括隐藏的对象)以摆脱任何先前的方法定义,这样才能真正正常生效。
这个其实是有文档记录的,但是不是很清楚;请参阅 Writing R Extensions 的 1.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"。