I am working with R and I have created a new subset
method for objects of class new_object
. Here is my function:
setGeneric('subset', function(x, i) standardGeneric('subset'))
setMethod('subset', 'new_object', function(x, i) {
# ... my code ...
# subset new_object
})
This works perfectly for new_object
. However, it seems to interfere with the subset operation of other objects, like seurat
objects. I get an error when I try to subset a seurat object after loading my new subset method.
The inheritance method for the 'subset' function with the 'Seurat' tag could not be found.
I would like the subset method to work as usual for all other types of objects, except for new_object
, for which I want to use my new subset method.
How can I define a new subset method for a specific class without affecting other objects in R?
In a clean, newly open R, run the subset
without the braces to see what this object is
> subset
function (x, ...)
UseMethod("subset")
<bytecode: 0x0000019b6e422730>
<environment: namespace:base>
So this is a S3 generic function with arguments x
, ...
and resides in package base
. Thus, when you call setGeneric('subset', function(x, i) standardGeneric('subset'))
, you create a new generic function with arguments x
, i
which is different than the existing arguments x
, ...
for subset
defined in package base
.
The solution is to call setGeneric("subset")
to make the existing function (subset
in package base
) become an S4 generic function.
> setGeneric("subset")
> setClass("new_object")
> setMethod("subset", "new_object", function(x, i, ...) {
# ... your code here ...
# subset new_object
# below is an example
print(x)
})
> subset
standardGeneric for "subset" defined from package "base"
function (x, ...)
standardGeneric("subset")
<environment: 0x000001f4839ab3b8>
Methods may be defined for arguments: x
Use showMethods(subset) for currently available ones.
> showMethods("subset", includeDefs = TRUE)
Function: subset (package base)
x="ANY"
function (x, ...)
UseMethod("subset")
x="new_object"
function (x, ...)
{
.local <- function (x, i, ...)
{
print(x)
}
.local(x, ...)
}
As you can see from showMethods("subset", includeDefs = TRUE)
, when you call this S4 subset
with x
of class new_object
, it will dispatch to your custom methods. Calling with any other class, it will utilize the existing S3 dispatch mechanism (i.e., UseMethod
).
Note: A good practice is for your method to have all the arguments of the generic, including … if the generic does, in this case, setMethod("subset", "new_object", function(x, i, ...) {# your code here ...}
(many thank for @JDL for introducing me this point).