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.

È stato utile?

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)) })
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top