Method hiding

Steven Schveighoffer schveiguy at yahoo.com
Thu May 27 14:11:55 PDT 2010


On Thu, 27 May 2010 17:00:08 -0400, bearophile <bearophileHUGS at lycos.com>  
wrote:

> While answering to Larry Luther in a long thread in D.learn:
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=19913
>
> I have found an interesting difference that I didn't know between Java  
> and D. Here I have reduced the test cases:
>
>
> // Java code
> class A {
>     void foo(A a) {}
> }
> class B extends A {
>     void foo(B b) {}
>
>     public static void main(String[] args) {
>         A a = new A();
>         B b = new B();
>         b.foo(a);
>     }
> }
>
>
>
> // D2 code
> class A {
>     void foo(A a) {}
> }
> class B : A {
>     void foo(B b) {}
> }
> void main() {
>     A a = new A;
>     B b = new B;
>     b.foo(a);// comment this out and use warnings
> }
>
>
> If you comment out the last line in the D2 code, and you use warnings,  
> DMD tells you at compile time:
>
> test.d(5): Error: class test.B test.A.foo(A a) is hidden by B
>
>
> If you uncomment that line DMD shows:
>
> test.d(12): Error: function test.B.foo (B b) is not callable using  
> argument types (A)
> test.d(12): Error: cannot implicitly convert expression (a) of type  
> test.A to test.B
>
>
> While the Java code compiles and runs with no errors.
> It seems in D the B.foo() hides A.foo() even if there is no overriding  
> at all here.
>
> The presence of that warning tells me this is not an implementation bug,  
> D is designed this way on purpose. But what is the rationale behind this  
> difference (that at best will puzzle Java programmers trying to use D)?

This is actually the first question I posted on this newsgroup in 2007.   
It's called method "hijacking", look for it on the D website for a  
thorough explanation.  Note that this is actually the default behavior in  
C++ (I didn't know until I asked the question and tried it, it's pretty  
obscure).

But the behavior is overridable, you can do this:

class B : A {
   alias A.foo foo;
   void foo(A a) {}
}

Which means "also look at A for resolving foo."

However, doing this may lead to further issues.  I think if you had a  
class C that derived from B, calling B.foo(c) would result in an ambiguity  
without a cast.

-Steve


More information about the Digitalmars-d mailing list