问题
I am writing a small R package with the idea to submit it to Bioconductor in the future, which is why I decided to try out s4 classes. Unfortunately I had problems understanding when I should use setGeneric or not in my package, and the documentation for the setGeneric
method is for me more or less incomprehensible.
Concrete example:
- I created a s4 class called Foo
- I defined a method for the
[<-
operator usingsetMethod("[","Foo", ...)
- I defined a method for the
as.list
function usingsetMethod("as.list", "Foo",...)
- I avoided using
setGenerics
and exporting my methods in the namespace as I read somewhere that it's not needed for already defined generic functions
The problem now is that the [
accessor method works like a charm, but as.list
is not working. Even more confusing, when I import the library BiocGenerics by typing library(BiocGenerics)
at the R terminal, as.list
starts to work.
Question 1: how can I be sure that [
will always work? And it is not just a coincidence because I imported some libraries?
Question 2: what should I do to make as.list
work? Export the method in the namespace? use setGeneric
?
Question 3: I thought that as.list
started to work because setGeneric("as.list"...)
was used in the BiocGenerics package, but this does not seem to be the case, reading from here: http://www.bioconductor.org/packages/release/bioc/manuals/BiocGenerics/man/BiocGenerics.pdf
So why did as.list
start to work? Where was it defined?
回答1:
In an R session with only the base packages and methods loaded you can see that the generic for "[" is defined, and the generic for "as.list" is not
> 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
Loading BiocGenerics does define the generic for 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.
If your package is destined for use in Bioconductor, then re-use the generic from BiocGenerics. Do this with the following in your NAMESPACE file
import(methods)
import(BiocGenerics)
exportMethods("[", "as.list")
and with the following in your DESCRIPTION file
Imports: methods, BiocGenerics
If you do not import the generic from BiocGenerics, then your setMethod("as.list", ...)
will create it's own generic. In the context of Bioconductor, a user would have to say YourPkg::as.list(YourObject)
or BiocGenerics::as.list(NotYourObject)
which is clearly not a good idea.
You need to import(methods)
because in your interactive trials you're relying on the methods package to be on the search() path. But (a) R CMD BATCH runs without the methods package attached and (b) it is best practice to rely on symbols that are explicitly in your name space, rather than merely on the search path (and hence subject to masking by other packages or user functions with arbitrary behavior. This applies as much to the methods package as any other.
来源:https://stackoverflow.com/questions/28301188/r-when-to-use-setgeneric-or-export-a-s4-method-in-the-namespace