On Thu, 27 May 2010 17:00:08 -0400, bearophile <bearophileh...@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