views:

190

answers:

2

Wikipedia on the diamond problem:

"... the diamond problem is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If a method in D calls a method defined in A (and does not override the method), and B and C have overridden that method differently, then from which class does it inherit: B, or C?"

So the diamond looks like this:

  A
 / \
B   C
 \ /
  D

My question is, what happens if there is no such class A, but again B and C declare the same method, say foo(). Isn't this the same problem? Why is it then called diamond problem?

Example:

class B {
    public void foo() {...}
}

class C {
    public void foo() {...}
}

class D extends B, C {
}

new D().foo();
+2  A: 

Its not the same problem.

In the original problem, the overriden method can be called from A. In your problem this can't be the case because it does not excist.

In the diamond problem, the clash happens if class A calls the method Foo. Normally this is no problem. But in class D you can never know which instance of Foo needs to be called:

         +--------+
         |   A    |
         | Foo    |
         | Bar    |
         +--------+
            /  \
           /    \
          /      \
+--------+        +--------+
|   B    |        |   C    |
| Foo    |        | Foo    |
+--------+        +--------+
          \      /
           \    /
            \  /
         +--------+
         |   D    |
         |        |
         +--------+

In your problem, there is no common ancestor that can call the method. On class D there are two flavors of Foo you can chose from, but at least you know that there are two. And you can make a choice between the two.

+--------+        +--------+
|   B    |        |   C    |
| Foo    |        | Foo    |
+--------+        +--------+
          \      /
           \    /
            \  /
         +--------+
         |   D    |
         |        |
         +--------+

But, as always, you do not need multiple inheritance. You can use aggegration and interfaces to solve all these problems.

Gamecat
The Wikipedia article talks about calling foo() from D, though.And what about calling foo on a D from outside D like new D().foo() (also in my example)?
cretzel
+2  A: 

In the diamond problem, class D implicitly inherits the virtual method from class A. To call it, class D would call:

A::foo()

If both classes B and C override this method, then the problem comes of which actually gets called.

In your second example however, this isn't the case as class D would need to explicitly state which was being called:

B::foo()
C::foo()

So the problems are not actually the same. In the diamond problem you aren't referencing the derived classes, but their base class, hence the ambiguity.

That's how I understand it, anyway.

Note that I'm coming from a C++ background.

icabod
I don't know C++, but wouldn't it be the same problem if you'd call foo from outside D, say new D().foo()? Then the example without A would also be problematic, right?
cretzel
@cretzel, yes, in that case you also have a name clash problem.
Gamecat
I think in most cases the compiler (for C++ at least) will give an error due to the ambiguity. It has on the compilers I've used, I'm not sure what the C++ standard says about it.
icabod