R:何时在命名空间中使用 setGeneric 或导出 s4 方法

R: when to use setGeneric or export a s4 method in the namespace

我正在写一个小的 R 包,打算将来提交给 Bioconductor,这就是我决定试用 s4 classes 的原因。不幸的是,我在理解什么时候应该在我的包中使用 setGeneric 或不使用时遇到了问题,setGeneric 方法的文档对我来说或多或少是难以理解的。

具体例子:

  1. 我创建了一个名为 Foo
  2. 的 s4 class
  3. 我使用 setMethod("[","Foo", ...)
  4. [<- 运算符定义了一个方法
  5. 我使用 setMethod("as.list", "Foo",...)
  6. as.list 函数定义了一个方法
  7. 我避免使用 setGenerics 并在命名空间中导出我的方法,因为我在某处读到已经定义的通用函数不需要它

现在的问题是 [ 访问器方法很有效,但 as.list 不起作用。更令人困惑的是,当我通过在 R 终端输入 library(BiocGenerics) 导入库 BiocGenerics 时,as.list 开始工作。

问题 1:如何确保 [ 始终有效?这不仅仅是巧合,因为我导入了一些库?

问题2:我应该怎么做才能让as.list正常工作?导出命名空间中的方法?使用 setGeneric?

问题3:我以为as.list开始工作是因为setGeneric("as.list"...)被用在了BiocGenerics包中,但事实似乎并非如此,从这里阅读:http://www.bioconductor.org/packages/release/bioc/manuals/BiocGenerics/man/BiocGenerics.pdf
那么为什么 as.list 开始起作用了呢?它在哪里定义的?

在仅加载基本包和方法的 R 会话中,您可以看到定义了“[”的泛型,而 "as.list" 的泛型未定义

> getGeneric("[")
standardGeneric for "[" defined from package "base"

function (x, i, j, ..., drop = TRUE) 
standardGeneric("[", .Primitive("["))
<bytecode: 0x28f7990>
<environment: 0x28ebef0>
Methods may be defined for arguments: x, i, j, drop
Use  showMethods("[")  for currently available ones.
> getGeneric("as.list")
NULL

加载 BiocGenerics 确实为 as.list

定义了仿制药
> suppressPackageStartupMessages(library(BiocGenerics))
> getGeneric("as.list")
standardGeneric for "as.list" defined from package "base"

function (x, ...) 
standardGeneric("as.list")
<environment: 0x5969210>
Methods may be defined for arguments: x
Use  showMethods("as.list")  for currently available ones.

如果您的包注定要在 Bioconductor 中使用,请重新使用 BiocGenerics 中的仿制药。在您的 NAMESPACE 文件中执行以下操作

import(methods)
import(BiocGenerics)

exportMethods("[", "as.list")

并在您的 DESCRIPTION 文件中包含以下内容

Imports: methods, BiocGenerics

如果您不从 BiocGenerics 导入仿制药,那么您的 setMethod("as.list", ...) 将创建它自己的仿制药。在 Bioconductor 的上下文中,用户必须说 YourPkg::as.list(YourObject)BiocGenerics::as.list(NotYourObject),这显然不是一个好主意。

您需要 import(methods) 因为在您的交互式试验中,您依赖方法包位于 search() 路径上。但是 (a) R CMD BATCH 在没有附加方法包的情况下运行,并且 (b) 最佳做法是依赖明确 in 你的名字 space 的符号,而不仅仅是在搜索路径上(因此受到其他包或具有任意行为的用户函数的屏蔽。这与任何其他包一样适用于方法包。