3

I would like to create a S4 method 'myMethod' that dispatches not only on the class of the first argument of the function, but also on the value of one of the slot of this class.

for instance

myObject:
@slot1="A"
@...

I would like myMethod(myObject) to returns something different for slot1="A" and slot2="B".

Can I avoid to hardcode the 'if' in the code of 'myObject'?

RockScience
  • 17,932
  • 26
  • 89
  • 125

1 Answers1

4

A not completely uncommon pattern is to use small classes to provide multiple dispatch

setClass("Base")
A = setClass("A", contains="Base")
B = setClass("B", contains="Base")
My = setClass("My", representation(slot1="Base"))

setGeneric("do", function(x, y, ...) standardGeneric("do"))
setMethod("do", "My", function(x, y, ...) do(x, x@slot1, ...))

and then methods to handle the re-dispatch

setMethod("do", c("My", "A"), function(x, y, ...) "My-A")
setMethod("do", c("My", "B"), function(x, y, ...) "My-B")

In action:

>     My = setClass("My", representation(slot1="Base"))
>     a = My(slot1=A())
>     b = My(slot1=B())
>     do(a)
[1] "My-A"
>     do(b)
[1] "My-B"
Martin Morgan
  • 45,935
  • 7
  • 84
  • 112
  • This seems to dispatch on the class of the slot, rather than the value, as stated in the OP? – kevinykuo Mar 23 '17 at 14:29
  • I guess my assumption was that the slot values came from a limited set of possible values that could be easily represented as a class hierarchy. I guess this is also implied by the fact that one wanted to enumerate possible behaviors. But you're right, it's not dispatching on values per se. – Martin Morgan Mar 24 '17 at 00:51
  • Thanks. Is there a more elegant pattern to dispatch on values of slots than writing `if...else...` code in the method? I'm getting a package to work with another package so I want to avoid suggesting changes upstream. – kevinykuo Mar 24 '17 at 13:35