[R-pkg-devel] Is a double dispatch possible with two S3 classes?

Leonardo Silvestri lsilvestri at ztsdb.org
Sat Feb 18 07:43:51 CET 2017


On 02/16/2017 02:34 PM, Duncan Murdoch wrote:
> On 16/02/2017 11:52 AM, Leonardo Silvestri wrote:
>> Hello,
>>
>> I have stumbled upon an S3 class dispatch issue which is easily solved
>> using S4 classes, but I'd like to know if there is a way to solve it
>> without changing the type of class used.
>>
>> The problem is as follows. There is an S3 class 'foo' which is defined
>> in a package over which I don't have control. Then there is an S3 class
>> 'bar' derived from 'foo' in a package that can be modified.
>>
>> Here is some code for 'foo':
>>
>> as.foo <- function(x) {
>>    oldClass(x) <- "foo"
>>    x
>> }
>>
>> print.foo <- function(x, ...) print(paste(x, "foo"))
>>
>> "-.foo" <- function(e1, e2) "-.foo was called"
>>
>>
>> And here is some code for 'bar':
>>
>> as.bar <- function(x) {
>>    oldClass(x) <- c("bar", "foo")
>>    x
>> }
>>
>> print.bar <- function(x, ...) print(paste(x, "bar"))
>>
>>
>> Now the '-' operator must be defined in such a way that the behaviour is
>> different depending on the operand classes, and in particular
>> 'bar'-'bar' needs to be different from 'bar'-'foo'. If I define the
>> following function:
>>
>> "-.bar" <- function(e1, e2) "-.bar was called"
>>
>> then I get the following results.
>>
>> as.foo(1) - as.foo(2)     # uses '-.foo'
>> as.bar(1) - as.bar(2)     # uses '-.bar'
>> as.bar(1) - as.foo(2)     # uses '-.default' and issues
>>                            # Incompatible methods warning
>> as.foo(1) - as.bar(2)     # uses '-.default' and issues
>>                            # Incompatible methods warning
>>
>> So that seems like a dead end.
>>
>> If, overcoming an instinctive shudder of disgust, I redefine '-.foo' in
>> the "bar" package, I have checked that correctness is at the mercy of
>> the order of loading of the packages, even though the "bar" package
>> imports the "foo" package. So that doesn't seem to work either.
>>
>> Before committing to making 'bar' an S4 class, does anyone know if there
>> is another option that would allow 'bar' to remain an S3 class?
>
> I don't think so, though you could conceivably check whether things will
> work when bar is loaded, and fail with a message saying "bar must be
> loaded first!" or whatever.
>
> Duncan Murdoch
>

Thanks for the answer. Yes, that would be a possibility (using 'foo' in 
'Depends' rather than 'Imports' does guarantee the loading order). One 
downside though is that two packages can't play at that game 
simultaneously...

Leo



More information about the R-package-devel mailing list