6
votes

I have a trait that extends two other traits that have the same name for a function but its a bit different from the inside, I want to know how do I know which function will be invoked?

I have trait B that has print(), and trait C that has print(), if I inherit both of them like this:

trait A extends B with C {
    def print()
}

each print printing something else, which print will be invoked?

3

3 Answers

7
votes

In the particular case where you have name conflicts, you'll receive a compile time error. Assuming D is the implementing class:

class D extends A with C with B

def main(args: Array[String]): Unit = {
  val d = new D
  println(d.print())
}

You'll see:

Error:(25, 9) class D inherits conflicting members:
  method print in trait B of type ()Unit  and
  method print in trait C of type ()Unit
(Note: this can be resolved by declaring an override in class D.)
  class D extends A with B with C

However, If we help out the compiler by adding an override print() to D, and make it call super.print(), it will print the last trait in the linage which support a print method, i.e.:

trait A { }

trait B { def print() = println("hello") }

trait C { def print() = println("world") }

class D extends A with B with C {
  override def print(): Unit = super.print()
}

We'd get "world". If we switched B and C:

class D extends A with C with B {
  override def print(): Unit = super.print()
}

We'd get "hello".

1
votes

One of the most important features of Traits in the original Schärli, Ducassé, Nierstrasz, Black paper is conflict resolution via renaming and hiding. This feature is completely absent from Scala's Traits.

In Scala, conflicts are simply not allowed. They are detected and rejected by the type system. (The original paper was in the context of Smalltalk, which doesn't have a type system, so a different approach was used.)

0
votes

Scala compiler gives you compile error.

Why don't you see it yourself using Scala REPL.

scala> trait B { def print(): Unit = println("B") }
defined trait B

scala> trait C { def print(): Unit = println("C") }
defined trait C

scala> trait A extends B with C { def foo = print() }
cmd11.sc:1: trait A inherits conflicting members:
  method print in trait B of type ()Unit  and
  method print in trait C of type ()Unit
(Note: this can be resolved by declaring an override in trait A.)
trait A extends B with C { def foo = print() }
      ^
Compilation Failed

I think you can easily understand using the compiler error