+5  A: 

People claim Java knows no diamond problem. I can only have multiple inheritance with interfaces and since they have no implementation, I have no diamond problem. Is this really true?

yes, because you control the implementation of the interface in D. The method signature is the same between both interfaces (B/C), and seeing as interfaces have no implementation - no problems.

SnOrfus
See above - just because move has no implementation does not solve the problem - I still cannot implement move() in the D class in such a way, that it will work.
Mecki
Then let me rephrase: If you decide to implement a diamond pattern with interfaces, then it's your problem deciding HOW to implement it. There is, however, nothing implicitly wrong in doing it.
SnOrfus
By that logic, there's no diamond problem in MI, either: you just specify the order, if the default isn't desirable. This is just like SI+interfaces, except you don't have to write the dispatcher yourself.
Ken
it's still a diamond unless you can get to *either* implementation not always one or the other.
ShuggyCoUk
+3  A: 

I don't know Java, but if Interfaces B and C inherit from Interface A, and class D implements Interfaces B and C, then class D just implements the move method once, and it is A.Move that it should implement. As you say, the compiler has no problem with this.

From the example you give regarding the AmphibianVehicle implementing GroundVehicle and WaterVehicle, this could easily be solved by storing a reference to Environment, for example, and exposing a Surface Property on Environment that the Move method of AmphibianVehicle would inspect. No need for this to be passed as a parameter.

You are right in the sense that it is something for the programmer to solve, but at least it compiles and should not be a 'problem'.

Patrick McDonald
A: 

I realize that this is a specific instance, not a general solution, but it sounds like you need an additional system to determine state and decide on which kind of move() the vehicle would perform.

It seems that in the case of an amphibious vehicle, the caller (let's say "throttle") would have no idea of the state of the water/ground, but an intermediate determining object like "transmission" in conjunction with "traction control" might figure it out, then call move() with the proper parameter move(wheels) or move(prop).

willoller
+5  A: 

C# has explicit interface implementation to partially deal with this. At least in the case where you've got one of the intermediate interfaces (an object thereof..)

However what probably happens is that the AmphibianVehicle object knows whether it is currently on water or land, and does the right thing.

Douglas Leeder
+10  A: 
MadKeithV
Good point. But doesn't multiple inheritance than always violates this principle as inheriting from two classes always makes the child class "wider"?
Mecki
If the two interfaces are completely orthogonal (i.e. they don't apply to the same concept) then you can get away with it. BUT... then you violate the single responsibility principle, which is another world of hurt.
MadKeithV
"narrow the purpose of the class" is called specialization :)
leppie
I disagree. An amphibious vehicle IS both a land and a water vehicle, it doesn't HAVE a land and a water vehicle. I can't see the example anymore, but the move method should specify a surface or something and that would make it work fine. If it doesn't, the vehicle interface should be improved.
Jordi
Using "IS A" as mnemonic for inheritance is flawed, that's in fact the whole reason for paying particular attention to correct Liskov Substitution. The example often cited is of squares and rectangles with the area method, where it's not trivial at all to get correct Liskov Substitution.
MadKeithV
+4  A: 

There is no Diamond Problem with Interface-based inheritance.

With Class-based inheritance, the multiple extended classes can have different implementation of a method, so there's ambiguity as to which method is actually used at runtime.

With Interface-based inheritance there's only one implemenation of the method, so there's no ambiguity.

EDIT: Actually, the same would apply to Class-based inheritance for methods declared as Abstract in the superclass.

Clayton
For the compiler, but I, as programmer, must make up my mind how to implement it. So instead of having abstract classes one could say multiple inheritance is fine and if there is any ambiguity, neither implementation is inherited, the programmer must overwrite the method.
Mecki
I think either you should be able to write the method such that it does the right thing in both cases, or you've made a mistake in trying to combine the classes in that way -- perhaps you need moveLand() and moveWater(), or some other approach.
rmeador
A: 

The problem really exists. In the sample the AmphibianVehicle-Class need another information - the surface. My prefered solution is to add a getter/setter method on the AmpibianVehicle class to change the surface member (enumeration). The implementation could now do the right thing and the class stay encapsulated.

p2u
A: 

I don't think that preventing concrete multiple inheritance is moving the problem from the compiler to the programmer. In the example you gave it would still be necessary for the programmer to specify to the compiler which implementation to use. There is no way the compiler could guess which is correct.

For your amphibian class, you could add a method to determine if the vehicle is on water or land and use this decide on the move method to use. This will preserve the parameterless interface.

move()
{

  if (this.isOnLand())
  {
     this.moveLikeLandVehicle();
  }
  else
  {
    this.moveLikeWaterVehicle();
  }
}
Dave Turvey
+3  A: 

If I know have an AmphibianVehicle interface, that inherits of GroundVehicle and WaterVehicle, how would I implement it's move() method?

You would provide the implementation suitable for AmphibianVehicles.

If a GroundVehicle moves "differently" (i.e. takes different parameters than a WaterVehicle), then AmphibianVehicle inherits two different methods, one for on water, one for on the ground. If this is not possible, then AmphibianVehicle shouldn't inherit from GroundVehicle and WaterVehicle.

Is a diamond problem always the cause of bad class design and something neither programmer nor compiler needs to solve, because it shouldn't exist in the first place?

If it's due to bad class design, it is the programmer that needs to solve it, since the compiler wouldn't know how.

eljenso
A: 

You can have the diamond problem in C++ (that allows multiple inheritance), but not in Java or in C#. There is no way for inheriting from two classes. Implement two interfaces with the same method declaration doesn't implies in this situation, since the concrete method implementation can only be made at the class.

Victor Rodrigues
The diamond problem still exists to a certain extent in java for importing libraries. It is partially solved by full name qualification, but theres the possibility that code you have already written using class X could be made ambiguous by importing another library that defines a class X.
B T
+1  A: 

In this case, it would probably be most advantageous to have AmphibiousVehicle be a subclass of Vehicle (sibling of WaterVehicle and LandVehicle), so as to completely avoid the problem in the first place. It would probably be more correct anyway, since an amphibious vehicle isn't a water vehicle or a land vehicle, it's a different thing altogether.

Kibbee
While this is a good solution, however it means you must rewrite all the code you wrote for the other two child classes that would actually work quite well for AmphibiousVehicle as well... good solution, but destroys the idea behind implementation inheritance somewhat
Mecki
Only if a lot of the functionality in the amphibious vehicle is the same as the water vehicle and land vehicle. If something inherits from 2 objects that are almost complete opposites, most of it would probably have to be rewritten anyway.
Kibbee
I think semantically it's most correct to do it the Diamond way. This is especially clear if WaterVehicle and LandVehicle implement some methods not directly inherited from Vehicle (like isSinking or inTrafficJam). AmphibiousVehicle should be able to do both.
Jordi
Actually, LandVehicle would be able to implement isSinking also, if you want to get specific about it.
Kibbee
+6  A: 

In your example, move() belongs to the Vehicle interface and defines the contract "going from point A to point B".

When GroundVehicle and WaterVehicle extend Vehicle, they implicitly inherit this contract (analogy: List.contains inherits its contract from Collection.contains -- imagine if it specified something different!).

So when the concrete AmphibianVehicle implements move(), the contract it really needs to respect is Vehicle's. There is a diamond, but the contract doesn't change whether you consider one side of the diamond or the other (or I would call that a design problem).

If you need the contract of "moving" to embody the notion of surface, don't define it in a type that doesn't model this notion:

public interface GroundVehicle extends Vehicle {
    void ride();
}
public interface WaterVehicle extends Vehicle {
    void sail();
}

(analogy: get(int)'s contract is defined by the List interface. It couldn't possibly be defined by Collection, as collections are not necessarily ordered)

Or refactor your generic interface to add the notion:

public interface Vehicle {
    void move(Surface s) throws UnsupportedSurfaceException;
}

The only problem I see when implementing multiple interfaces is when two methods from totally unrelated interfaces happen to collide:

public interface Vehicle {
    void move();
}
public interface GraphicalComponent {
    void move(); // move the graphical component on a screen
}
// Used in a graphical program to manage a fleet of vehicles:
public class Car implements Vehicle, GraphicalComponent {
    void move() {
        // ???
    }
}

But then that wouldn't be a diamond. More like an upside-down triangle.

Olivier
I like your example with Vehicle and GraphicalComponent - not a real diamond issue, but this is also one of the big problems you can get with interfaces, where the fact that no implementation is inherited actually does not save your day ;-)
Mecki
Great answer! Although it would have been nice if it explicitly contained that the diamond problem is not really that big a problem and that allowing MI with interfaces does not really save much trouble.
Jordi
+1  A: 

If move() has semantic differences based on it being Ground or Water (rather than GroundVehicle and WaterVehicle interfaces both themselves extending GeneralVehicle interface that has the move() signature) but it is expected that you will mix and match ground and water implementers then your example one is really one of a poorly designed api.

The real issue is when the name collision is, effectively, accidental. for example (very synthetic):

interface Destructible
{
    void Wear();
    void Rip();
}

interface Garment
{
    void Wear();
    void Disrobe();
}

If you have a Jacket which you wish to be both a garment, and destructible you will have a name collision on the (legitimately named) wear method.

Java has no solution for this (the same is true for several other statically typed languages). Dynamic programming languages will have a similar issue, even without the diamond or inheritance, it's just a name collision (an inherent potential issue with Duck Typing).

.Net has the concept of explicit interface implementations whereby a class can define two methods of the same name and signature so long as both are marked to two different interfaces. The determination of the relevant method to call is based on compile time known interface of the variable (or if by reflection by the explicit choice of the callee)

That reasonable, likely name collisions are so hard to come by and that java has not been pilloried as unusable for not providing the explicit interface implementations would suggest that the problem is not a significant one for real world use.

ShuggyCoUk
Java does not have a problem with this. A java class that implements Destructible and Garment will have 3 methods, Wear(), Rip(), and Disrobe(). The fact that "wear" can have 2 meanings in English is a name problem, not a Java problem. Wear() will do whatever you code it to do, regardless of name.
Clayton
Exactly, but wear cannot determine whether it was being invoked in the context of being asked to be worn or to degrade itself. This despite that fact that such information could have been made available to the type system at compile. Thus it cannot effectively do both.
ShuggyCoUk
Conflicting desires due to a name collision which cannot be resolved *is* the diamond problem. If you can include information to resolve it it stops being a problem and by definition is not a diamond anymore
ShuggyCoUk
A: 

The diamond problem in C++ is already solved: use virtual inheritance. Or better yet, don't be lazy and inherit when it's not necessary (or unavoidable). As for the example you gave, this could be solved by redefining what it means to be capable of driving on the ground or in the water. Does the ability to move through water really define a water-based vehicle or is just something the vehicle is able to do? I'd rather think that the move() function you described has some sort of logic behind it that asks "where am I and can I actually move here?" The equivalent of a bool canMove() function that depends on the current state and the inherent abilities of the vehicle. And you don't need multiple inheritance to solve that problem. Just use a mixin that answers the question in different ways depending on what's possible and takes the superclass as a template parameter so the virtual canMove function will be visible through the inheritance chain.

Michel
A: 

Actually, if Student and Teacher are both interfaces, it does in fact solve your problem. If they are interfaces, then getDepartment is simply a method that must appear in your GradTeachingFellow class. The fact that both the Student and Teacher interfaces enforce that interface isn't a conflict at all. Implementing getDepartment in your GradTeachingFellow class would satify both interfaces without any diamond problem.

BUT, as pointed out in a comment, this doesn't solve the problem of a GradStudent teaching/being a TA in one department, and being a student in another. Encapsulation is probably what you want here:

public class Student {
  String getDepartment() {
    return "Economics";
  }
}

public class Teacher {
  String getDepartment() {
    return "Computer Engineering";
  }
}

public class GradStudent {
  Student learning;
  Teacher teaching;

  public String getDepartment() {
    return leraning.getDepartment()+" and "+teaching.getDepartment(); // or some such
  }

  public String getLearningDepartment() {
    return leraning.getDepartment();
  }

  public String getTeachingDepartment() {
    return teaching.getDepartment();
  }
}

It doesn't matter than a GradStudent doesn't conceptually "have" a teacher and student - encapsulation is still the way to go.

B T
And how does that solve the problem, that GradTeachingFellow may be student in one department, but teacher in another one? Even if it is an interface, it will fail, just not at the code level.
Mecki
You're right, it solves the problem at the code level, but not at the semantic level. In the case you're talking about, inheritance may not be what you want here - maybe you want encapsulation. This wouldn't work in Java, but alternatively, it would be semantically possible to inherit both methods under aliased names - e.g. getTeachingDepartment() and getStudentDepartment(). Java isn't a very flexible language, so encapsulation is probably your best bet for a GradStudent class.
B T
+1  A: 

The problem that you're seeing in the Student / Teacher example is simply that your data model is wrong, or at least insufficient.

The Student and Teacher classes are conflating two different concepts of "department" by using the same name for each of them. If you want to use this kind of inheritance, you should instead define something like "getTeachingDepartment" in Teacher and "getResearchDepartment" in Student. Your GradStudent, which is both a Teacher and a Student, implements both.

Of course, given the realities of graduate school, even this model is probably insufficient.

asdfwera
You are probably right; the problem is just that interfaces like this tend to grow over the time and whoever created the Teacher interface might be a different person than the person who crated the Student interface, and neither one has ever considered that there might be a class having both interfaces at the same time. Maybe a third person created the GradTeachingFellow class and that before Student or Teacher had a department method at all.
Mecki
What I'm trying to say here is that in an ideal OO language, different people make different classes and ideally no matter how the inheritance hierarchy looks like or how those classes are altered, nothing would ever break. This is far from reality, though. IMHO multiple inheritance only works great if: 1. there is inheritance beyond the scope of a library/binary; 2. everyone working on the library/binary has access to the source code and permission to change everything, if he likes. If either one is not true, it's better to stick with single inheritance (much less headache).
Mecki