20

(Note: I used 'error' instead of 'problem' in the title for obvious reasons.. ;) ).

I did some basic reading on Traits in Scala. They're similar to Interfaces in Java or C#, but they do allow for default implementation of a method.

I was wondering: can't this cause a case of the "diamond problem", which is why many languages avoid multiple inheritance in the first place?

If so, how does Scala handle this?

Aviv Cohn
  • 21,538

2 Answers2

28

The diamond problem is the inability to decide which implementation of the method to choose. Scala solves this by defining which implementation to choose as part of the language specifications(read the part about Scala in this Wikipedia article).

Ofcourse, same order definition could also be used in class multiple inheritance, so why bother with traits?

The reason IMO is constructors. Constructors have several limitations that regular methods don't have - they can only be called once per object, they have to be called for each new object, and a child class' constructor must call it's parent's constructor as it's first instruction(most languages will do it implicitly for you if you don't need to pass parameters).

If B and C inherit A, and D inherits B and C, and both B and C's constructors call A's constructor, then D's constructor will call A's constructor twice. Defining which implementations to choose like Scala did with methods won't work here because both B's and C's constructors must be called.

Traits avoid this problem since they don't have constructors.

doubleYou
  • 2,867
  • 1
  • 13
  • 26
Idan Arye
  • 12,145
26

Scala avoids the diamond problem by something called "trait linearization". Basically, it looks up the method implementation in the traits you extend from right to left. Simple example:

trait Base {
   def op: String
}

trait Foo extends Base {
   override def op = "foo"
}

trait Bar extends Base {
   override def op = "bar"
}

class A extends Foo with Bar
class B extends Bar with Foo

(new A).op
// res0: String = bar

(new B).op
// res1: String = foo

Having said that, the list of traits it looks up might contain more than the ones you explicitly gave, since they might extend other traits. A detailed explanation is given here: Traits as stackable modifications and a more complete example of the linearization here: Why not multiple inheritance?

I believe in other programming languages this behavior is sometimes referred to as "Method resolution order" or "MRO".

lutzh
  • 505