简体   繁体   English

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

[英]How to use S3 methods from another package which uses export rather than S3method in its namespace without using Depends or library()

I'm working on an R package at present and trying to follow the best practice guidelines provided by Hadley Wickham at http://r-pkgs.had.co.nz . 我目前正在制作一个R包,并试图遵循Hadley Wickham在http://r-pkgs.had.co.nz提供的最佳实践指南。 As part of this, I'm aiming to have all of the package dependencies within the Imports section of the DESCRIPTION file rather than the Depends since I agree with the philosophy of not unnecessarily altering the global environment (something that many CRAN and Bioconductor packages don't seem to follow). 作为其中的一部分,我的目标是在DESCRIPTION文件的Imports部分中拥有所有的包依赖,而不是取决于因为我同意不会不必要地改变全球环境的理念(许多CRAN和Bioconductor包都没有似乎跟着)。

I want to use functions within the Bioconductor package rhdf5 within one of my package functions, in particular h5write() . 我想在我的一个包函数中使用Bioconductor包rhdf5中的函数,特别是h5write() The issue I've now run into is that it doesn't have its S3 methods declared as such in its NAMESPACE. 我现在遇到的问题是它的NAMESPACE中没有声明它的S3方法。 They are declared using (eg) 它们被声明使用(例如)

export(h5write.default)
export(h5writeDataset.matrix)

rather than 而不是

S3method(h5write, default)
S3method(h5writeDataset, matrix)

The generic h5write is defined as: 通用h5write定义为:

h5write <- function(obj, file, name, ...) {
res <- UseMethod("h5write")
  invisible(res)
}

In practice, this means that calls to rhdf5::h5write fail because there is no appropriate h5write method registered. 实际上,这意味着对rhdf5 :: h5write的调用失败,因为没有注册适当的h5write方法。

As far as I can see, there are three solutions to this: 据我所知,有三种解决方案:

  1. Use Depends rather than Imports in the DESCRIPTION file. 在DESCRIPTION文件中使用Depends而不是Imports
  2. Use library("rhdf5") or require("rhdf5") in the code for the relevant function. 在相关函数的代码中使用library("rhdf5")require("rhdf5")
  3. Amend the NAMESPACE file for rhdf5 to use S3methods() rather than export() . 修改rhdf5的NAMESPACE文件以使用S3methods()而不是export()

All of these have disadvantages. 所有这些都有缺点。 Option 1 means that the package is loaded and attached to the global environment even if the relevant function in my package is never called. 选项1表示即使从不调用我的包中的相关函数,也会加载包并将其附加到全局环境。 Option 2 means use of library in a package, which while again attaches the package to the global environment, and is also deprecated per Hadley Wickham's guidelines. 选项2意味着在包中使用library ,同时将包附加到全局环境,并且根据Hadley Wickham的指南也弃用。 Option 3 would mean relying on the other package author to update their package on Bioconductor and also means that the S3 methods are no longer exported which could in turn break other packages which rely on calling them explicitly. 选项3意味着依赖于另一个包作者来更新他们在Bioconductor上的包,并且还意味着不再导出S3方法,这反过来又会破坏依赖于明确调用它们的其他包。

Have I missed another alternative? 我错过了另一种选择吗? I've looked elsewhere on StackOverflow and found the following somewhat relevant questions Importing S3 method from another package and How to export S3 method so it is available in namespace? 我已经在其他地方查看了StackOverflow并发现以下有些相关的问题从另一个包导入S3方法以及如何导出S3方法以便在命名空间中可用? but nothing that directly addresses my issue. 但没有任何直接解决我的问题。 Of note, the key difference from the first of these two is that the generic and the method are both in the same package, but the issue is the use of export rather than S3method . 值得注意的是,与这两者中的第一个的关键区别在于泛型和方法都在同一个包中,但问题是使用export而不是S3method

Sample code to reproduce the error (without needing to create a package): 用于重现错误的示例代码(无需创建包):

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')

Alternatively, there is a skeleton package at https://github.com/NikNakk/s3issuedemo which provides a single function demonstrateIssue() which reproduces the error message. 或者, https://github.com/NikNakk/s3issuedemo上有一个框架包,它提供了一个函数demonstrateIssue() ,它可以重现错误消息。 It can be installed using devtools::install_github("NikNakk/s3issuedemo") . 它可以使用devtools::install_github("NikNakk/s3issuedemo")

The key here is to import the specific methods in addition to the generic you want to use. 这里的关键是除了要使用的泛型之外还导入特定方法。 Here is how you can get it to work for the default method. 以下是如何使其适用于默认方法。

Note : this assumes that the test.h5 file already exists. 注意 :这假定test.h5文件已存在。

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

I also have put up my own small package demonstrating this here . 我也在这里展示了自己的小包装。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM