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

Duncan Murdoch murdoch.duncan at gmail.com
Thu Feb 16 20:34:46 CET 2017


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



More information about the R-package-devel mailing list