Reputation: 25
I have been trying to understands Mixins and I found on Wikipedia that Mixins can be used to avoid the diamond problem. Link
How the Diamond problem is avoided by using Mixins (Or Interfaces in java)
Upvotes: 1
Views: 599
Reputation: 103229
That wikipedia article certainly needs some love at the time I'm writing this answer.
Given that you tagged in java, specifically:
Parent1
and Parent2
as parent types (be it because of a hypothetical extends Parent1, Parent2
or be it because extends Parent1 implements Parent2
or implements Parent1, Parent2
- those last 2 are valid in java, and both Parent1 as well as Parent2 have an identical method (say, void method()
), then which implementation 'wins'?Parent1
or Parent2
(both interfaces in this example), you must write an implementation for void foo()
. If you implement them both, you... must write an implementation for void foo()
. No problem there.Thus, let's continue by defining 'the diamond problem' as "Avoid having the ordering matter". Furthermore, as it is java, you still can't extend more than one thing, so we're really just talking about the ordering of interfaces. If you write implements Parent1, Parent2
, is there any change whatsoever if you edit that source file to read implements Parent2, Parent1
instead? In C++ the answer: "Yes, that matters". In java, the answer is supposed to be: "No, that is a meaningless change". Let's see how java has 'solved' the problem given that default methods now exist in java:
extends Parent1 implements Parent2
Given:
class Parent1 {
public void foo() {
System.out.println("Parent1.foo");
}
}
interface Parent2 {
default void foo() {
System.out.println("Parent2.foo");
}
}
class Foo extends Parent1 implements Parent2 {}
Then this will compile, and new Foo().foo();
would print Parent1.foo
. That's because in java, the class hierarchy wins: The interface merely specifies a default implementation, to be used if no other impl is available. There IS another available (from Parent1
), thus, it wins.
Whether you consider this a 'fix' to the diamond problem depends on how you define the term 'Diamond Problem'. There is no one set definition that is universally agreed upon.
implements Parent1, Parent2
Given:
interface Parent1 {
default void foo() {
System.out.println("Parent1.foo");
}
}
interface Parent2 {
default void foo() {
System.out.println("Parent2.foo");
}
}
class Foo implements Parent1, Parent2 {}
then the above does not compile. Javac detects that there is a conflict (2 competing implementations of the same method), and as order must never matter, java CANNOT give one of the two preferential treatment just because it's listed first.
Hence, instead, javac will just error. You can fix it by writing an impl for that method explicitly. You can even choose one (or both!) of the parent impls:
class Foo implements Parent1, Parent2 {
@Override public void foo() {
Parent1.super.foo();
Parent2.super.foo();
}
}
Now new Foo().foo()
would print:
Parent1.foo
Parent2.foo
Hence, even with default methods in java now being a thing (which is exactly what a "mix-in" is, so even though that wikipedia doesn't list java as a language that has mix-ins, the wikipedia page is wrong, and in fact later says so in the section about java!) - order still does not matter.
Upvotes: 6