digitalmars.D - Method hiding
- bearophile (37/37) May 27 2010 While answering to Larry Luther in a long thread in D.learn:
- Steven Schveighoffer (17/59) May 27 2010 This is actually the first question I posted on this newsgroup in 2007. ...
- bearophile (10/26) May 27 2010 I have read this, about in the middle:
- bearophile (42/45) May 27 2010 This is D code:
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)? Bye, bearophile
May 27 2010
On Thu, 27 May 2010 17:00:08 -0400, bearophile <bearophileHUGS 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
May 27 2010
Steven Schveighoffer:This is actually the first question I posted on this newsgroup in 2007.I am very late then, sorry for not asking this is D.learn.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).I have read this, about in the middle: http://www.digitalmars.com/d/2.0/hijack.html Thank you for the explanations and thanks to Walter for that page. I vaguely remember reading that page, but I did remember it only about free functions. I appreciate D design here :-)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."OK.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.I will experiment some about this. Thank you and bye, bearophile
May 27 2010
Steven Schveighoffer: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.This is D code: import std.c.stdio: puts; class A { void foo(A a) { puts("A.foo"); } } class B : A { alias A.foo foo; void foo(B b) { puts("B.foo"); } } class C : B {} void main() { A a = new A(); B b = new B(); C c = new C(); b.foo(a); // Prints: A.foo b.foo(c); // Prints: B.foo } -------------------- A Java translation: class A { void foo(A a) { System.out.println("A.foo"); } } class B extends A { void foo(B b) { System.out.println("B.foo"); } } class C extends B { public static void main(String[] args) { A a = new A(); B b = new B(); C c = new C(); b.foo(a); // Prints: A.foo b.foo(c); // Prints: B.foo } } This time they both call the same methods, b.foo(c) calls B.foo(B), probably because C is closer to B than A in the hierarchy :-) In normal programs I'd like to avoid writing this code. Bye, bearophile
May 27 2010