如何在其命名空间中使用导出而不是S3method的另一个包中的S3方法,而不使用Depends或library()

Nic*_*edy 12 r package r-s3 r-package

我目前正在制作一个R包,并试图遵循Hadley Wickham在http://r-pkgs.had.co.nz提供的最佳实践指南.作为其中的一部分,我的目标是在DESCRIPTION文件的Imports部分中拥有所有的包依赖,而不是取决于因为我同意不会不必要地改变全球环境的理念(许多CRAN和Bioconductor包都没有似乎跟着).

我想在我的一个包函数中使用Bioconductor包rhdf5中的函数h5write().我现在遇到的问题是它的NAMESPACE中没有声明它的S3方法.它们是使用(例如)声明的

export(h5write.default)
export(h5writeDataset.matrix)
Run Code Online (Sandbox Code Playgroud)

而不是

S3method(h5write, default)
S3method(h5writeDataset, matrix)
Run Code Online (Sandbox Code Playgroud)

通用h5write定义为:

h5write <- function(obj, file, name, ...) {
res <- UseMethod("h5write")
  invisible(res)
}
Run Code Online (Sandbox Code Playgroud)

实际上,这意味着对rhdf5 :: h5write的调用失败,因为没有注册适当的h5write方法.

据我所知,有三种解决方案:

  1. 使用Depends而不是Imports在DESCRIPTION文件中.
  2. 使用library("rhdf5")require("rhdf5")代码中的相关功能.
  3. 修改NAMESPACE文件以使用rhdf5 S3methods()而不是export().

所有这些都有缺点.选项1表示即使从不调用我的包中的相关函数,也会加载包并将其附加到全局环境.选项2意味着library在包中使用,同时再将包附加到全球环境中,并且根据Hadley Wickham的指南也弃用.选项3意味着依赖于另一个包作者来更新他们在Bioconductor上的包,并且还意味着不再导出S3方法,这反过来又会破坏依赖于明确调用它们的其他包.

我错过了另一种选择吗?我已经在其他地方查看了StackOverflow并发现以下有些相关的问题从另一个包导入S3方法以及 如何导出S3方法以便在命名空间中可用?但没有任何直接解决我的问题.值得注意的是,与这两者中的第一个的关键区别在于泛型和方法都在同一个包中,但问题在于使用export而不是S3method.

用于重现错误的示例代码(无需创建包):

loadNamespace("rhdf5")
rdhf5::h5write(1:4, "test.h5", "test")

Error in UseMethod("h5write") : 
no applicable method for 'h5write' applied to an object of class
"c('integer', 'numeric')
Run Code Online (Sandbox Code Playgroud)

或者,https://github.com/NikNakk/s3issuedemo上有一个框架包,它提供了一个单独的函数demonstrateIssue()来重现错误消息.它可以使用安装devtools::install_github("NikNakk/s3issuedemo").

cde*_*man 9

这里的关键是除了要使用的泛型之外还导入特定方法.以下是如何使其适用于默认方法.

注意:这假定该test.h5文件已存在.

#' @importFrom rhdf5 h5write.default
#' @importFrom rhdf5 h5write
#' @export
myFun <- function(){
    h5write(1:4, "test.h5", "test")
}
Run Code Online (Sandbox Code Playgroud)

我也在这里展示了自己的小包装.