You could use a class union (see ?setClassUnion
for details):
setClassUnion("BorC", c("B", "C"))
setMethod("exec", c("A", "BorC"), function(x, y) { return(f(y)) })
Domanda
I am currently developing an R package grouping all the functionality I am using in my lab projects. I am doing it, not only for the sake of it, but also for learning S4. I am experiencing now a conceptual problem. Imagine I have the following classes and methods:
setClass('A', representation(a='numeric'))
setGeneric('exec', function(x, y) standardGeneric('exec'))
setClass('B', representation(b='numeric'))
setGeneric('f', function(x) standardGeneric('f'))
setMethod('f', 'B',
function(x) {
return(42)
})
setClass('C', representation(c='numeric'))
setMethod('f', 'C',
function(x) {
return(24)
})
In the real case, just to provide some context, A is a class belonging to a hierarchy implementing the Command design pattern. B and C would be classes representing completely different things but with a common interface (in this case, the f method). Returning to the real thing, an example of the common f method would be nrow.
In other programming language, I think I would get along just by defining a method taking an abstract interface (declaring the f method) as an argument. Thus, every class implementing that interface could be passed as an argument to the command.
Option A:
Declare a method implementation for each of the classes.
setMethod('exec', c('A', 'B'),
function(x, y) {
return(f(y))
})
setMethod('exec', c('A', 'C'),
function(x, y) {
return(f(y))
})
Option B:
Implement a method with ANY signature, and then controlling if the class implements the given interface.
setMethod('exec', c('A', 'ANY'),
function(x, y) {
if (!hasMethod('f', class(y))) {
stop('Y must implement method f!')
} else {
return(f(y))
}
})
If classes B and C were only a few, and I could find a common ancestor, I would have no problem with option A (taking the common ancestor or a class union as signature), but in this case there could be many classes like B and D, all in different hierarchies and with the only characteristic in common of implementing nrow, ncol and the '[' operator.
I prefer the B option because I can explicitly state the interface compliance. But I do not know if there is a better idiom in R for this situation.
Any hint or help would be much appreciated.
Soluzione
You could use a class union (see ?setClassUnion
for details):
setClassUnion("BorC", c("B", "C"))
setMethod("exec", c("A", "BorC"), function(x, y) { return(f(y)) })