[R] Understanding S4 method dispatch
Simon Zehnder
szehnder at uni-bonn.de
Wed Aug 14 12:51:42 CEST 2013
Ambiguity is indeed detected by R and the user is informed on it. But in the case of Hadley's example, I still believe, that the specific multiple inheritance structure creates this behavior. If you call:
showMethods("f")
Function: f (package .GlobalEnv)
x="A", y="A"
x="AB", y="AB"
(inherited from: x="B", y="B")
x="B", y="B"
you see, that AB inherited the method from B. As B inherits already from A and AB does as well, AB would have two A objects, the one from its inheritance from A and the one from B. In the case of direct inheritance, the only slot is the .xData slot, which is NULL. If one class contains another one, it contains all its slots. As the .xData slot is the same for each class A, B and AB, R must remove the ambiguity of slots, this is done by allowing only one slot .xData, which is the one from B. So in some way A is hidden by B in AB - but this is actually a common technique in OOP. In C++ for example we have the same problem and we can define which members should be inherited if multiple inheritance is aware, by using the keyword 'virtual'.
Towards Hervé's second point:
If we build a class C:
setClass("C", contains = c("A"))
setMethod("f", signature("C", "C"), function(x, y) "C-C")
And then construct a multiple inheritance structure within a class BC:
setClass("BC", contains = c("B", "C"))
bc <- new("BC")
we see, that indeed the first lexicographical signature is chosen:
showMethods("f")
Function: f (package .GlobalEnv)
x="A", y="A"
x="B", y="B"
x="BC", y="BC"
(inherited from: x="B", y="B")
x="C", y="C"
f(bc, bc)
[1] "B-B"
In this case, we have a 'true' tie in the inheritance structure: B from A and C from A, any one of the two As have to be taken into the BC object and the one from B is chosen. But method dispatch is in this case independent of the second level inheritance. B and C are not related directly to each other, so method dispatch is chosen lexicographically.
In my opinion the reason for the behavior lies in the specific multiple inheritance structure between AB, B and A.
Best
Simon
On Aug 14, 2013, at 2:11 AM, Hervé Pagès <hpages at fhcrc.org> wrote:
> Hi Hadley,
>
> I suspect that the dispatch algorithm doesn't realize that selection
> is ambiguous in your example. For 2 reasons:
>
> (1) When it does realize it, it notifies the user:
>
> setClass("A", "NULL")
> setGeneric("f", function(x, y) standardGeneric("f"))
> setMethod("f", signature("A", "ANY"), function(x, y) "A-ANY")
> setMethod("f", signature("ANY", "A"), function(x, y) "ANY-A")
> a <- new("A")
>
> Then:
>
> > f(a, a)
> Note: method with signature ‘A#ANY’ chosen for function ‘f’,
> target signature ‘A#A’.
> "ANY#A" would also be valid
> [1] "A-ANY"
>
> (2) When dispatch is ambiguous, the "first method lexicographically in
> the ordering" should be selected (according to ?Methods). So it
> should be A#A, not B#B.
>
> So it looks like a bug to me...
>
> Cheers,
> H.
>
>
> On 08/13/2013 06:08 AM, Hadley Wickham wrote:
>> Hi all,
>>
>> Any insight into the code below would be appreciated - I don't
>> understand why two methods which I think should have equal distance
>> from the call don't.
>>
>> Thanks!
>>
>> Hadley
>>
>> # Create simple class hierarchy
>> setClass("A", "NULL")
>> setClass("B", "A")
>>
>> a <- new("A")
>> b <- new("B")
>>
>> setGeneric("f", function(x, y) standardGeneric("f"))
>> setMethod("f", signature("A", "A"), function(x, y) "A-A")
>> setMethod("f", signature("B", "B"), function(x, y) "B-B")
>>
>> # These work as I expect
>> f(a, a)
>> f(b, b)
>>
>> setClass("AB", contains = c("A", "B"))
>> ab <- new("AB")
>>
>> # Why does this return B-B? Shouldn't both methods be an equal distance?
>> f(ab, ab)
>>
>> # These both return distance 1, as I expected
>> extends("AB", "A", fullInfo=TRUE)@distance
>> extends("AB", "B", fullInfo=TRUE)@distance
>> # So why is signature("B", "B") closer than signature("A", "A")
>>
>
> --
> Hervé Pagès
>
> Program in Computational Biology
> Division of Public Health Sciences
> Fred Hutchinson Cancer Research Center
> 1100 Fairview Ave. N, M1-B514
> P.O. Box 19024
> Seattle, WA 98109-1024
>
> E-mail: hpages at fhcrc.org
> Phone: (206) 667-5791
> Fax: (206) 667-1319
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
More information about the R-help
mailing list