8
votes

I have read over the internet that Traits in Scala are

interfaces that can provide concrete members

this means, traits are interface and we may provide body to methods in interface. I have a simple query here, if that is possible than why my below code shows error:

Error:(6, 8) object Car inherits conflicting members: method startEngine in trait Vehical of type => Unit and method startEngine in trait Motor of type => Unit (Note: this can be resolved by declaring an override in object Car.) object Car extends Vehical with Motor {

trait Vehical {
  def startEngine : Unit = {
    println("Vehical Start")
  }
  def stopEngine
}

trait Motor {
  def startEngine : Unit = {
    println("Motor Start")
  }
  def stopEngine
}

object Car extends Vehical with Motor {

  override def stopEngine : Unit = {
    println("Stop Engine")
  }

  def main(args: Array[String]): Unit = {
    Car.startEngine
    Car.stopEngine
  }
}

Being a java developer I would have not provided body inside interface but scala traits allowed this. If traits are not interface then I'll consider them as an abstract class, that means no interface allowed in scala.

Also please let me know how to resolve this ambiguity problem. How can I use my startEngine method in child class if the same method is available in multiple traits.

1
Similar thing has been asked here. But here's a quick answer: Trait is both, actually. Traits are mixins, but if you need a comparison with Java, they are exactly between interfaces and abstract classes. Similarity with interfaces is that a trait may be mixed into more than one class and that it cannot have a constructor with parameters. Similarity with abstract classes is that it can contain implementations for methods.slouc
very crisp ans thank you. Can you please let me know what makes to create Traits. I mean why Traits when we have Interface and Abstract Class.Pardeep Sharma
Hey, I just saw this comment now. @Yuval provided a good answer, I presume your question above is now deprecated :)slouc

1 Answers

8
votes

Being a java developer I would have not provided body inside interface but scala traits allowed this

A trait in Scala provides means of defining a default implementation, and so does Java starting version 8. In Scala, they are primarily used as mixins.

In regards to the compilation error, this arises from the fact that you have declared both Vehicle and Motor with a startEngine method, and that creates an ambiguity from the compilers point of view, since you're mixing in both implementations. To overcome this, you need to explicitly override the method in the implementing class/trait:

override def startEngine: Unit = super.startEngine

One important thing to note is that super here is referring to the last trait in the mixin chain which supplies a startEngine method, in this case Motor. This means that you'll see:

Motor Start
Stop Engine

Which I'd argue is not what you want.

What can be done is to require Vehicle to have a mixed in Motor implementation using self types:

trait Vehicle {
  self: Motor =>

  def startEngine: Unit = {
    println("Vehicle Start")
    startMotor
  }

  def stopEngine: Unit = {
    println("Stopping Engine")
    stopMotor
  }
}

And define your Motor methods in terms of motor only:

trait Motor {
  def startMotor: Unit = {
    println("Motor Start")
  }

  def stopMotor: Unit = {
    println("Stop Motor")
  }
}

And then you mixin everything:

object Car extends Vehicle with Motor

And call:

def main(args: Array[String]): Unit = {
  Car.startEngine
  Car.stopEngine
}

And you get:

Vehicle Start
Motor Start
Stopping Engine
Stop Motor