What is the difference between mixins and inheritance?

I think its very usage dependent. Scala being a multi-paradigm language makes it powerful as well as a bit confusing at times. I think Mixins are very powerful when used the right way. Mixins should be used to introduce behavior and reduce bolierplate.

A trait in Scala can have implementations and it is tempting to extend them and use them.

Traits could be used for inheritance. It can also be called mixins however that in my opinion is not the best way to use mixin behavior. In this case you could think of traits as Java Abstract Classes. Wherein you get subclasses that are "type of" the super class (the trait).

However Traits could be used as proper mixins as well. Now using a trait as a mixin depends on the implementation that is "how you mix it in". Mostly its a simple question to ask yourself . It is "Is the subclass of the trait truly a kind of the trait or are the behaviors in the trait behaviors that reduce boilerplate". Typically it is best implemented by mixing in traits to objects rather than extending the trait to create new classes.

For example consider the following example:

    //All future versions of DAO will extend this
trait AbstractDAO{
  def getRecords:String
  def updateRecords(records:String):Unit
}
//One concrete version
trait concreteDAO extends AbstractDAO{
  override def getRecords={"Here are records"}
  override def updateRecords(records:String){
    println("Updated "+records)
  }
}
//One concrete version
trait concreteDAO1 extends AbstractDAO{
  override def getRecords={"Records returned from DAO2"}
  override def updateRecords(records:String){
    println("Updated via DAO2"+records)
  }
}
//This trait just defines dependencies (in this case an instance of AbstractDAO) and defines operations based over that
trait service{
  this:AbstractDAO =>

  def updateRecordsViaDAO(record:String)={  
  updateRecords(record) 
  }
  def getRecordsViaDAO={
  getRecords
  }
}


object DI extends App{
  val wiredObject = new service with concreteDAO //injecting concrete DAO to the service and calling methods
  wiredObject.updateRecords("RECORD1")
  println(wiredObject.getRecords)

  val wiredObject1 = new service with concreteDAO1
  wiredObject1.updateRecords("RECORD2")
  println(wiredObject1.getRecords)

}

concreteDAO is a trait which extends AbstractDAO - This is inheritance

val wiredObject = new service with concreteDAO - This is proper mixin behavior Since the service trait mandates the mixin of a AbstractDAO. It would be just wrong for Service to extend ConcreteDAO anyways because the service required AbstractDAO it is not a type of AbstractDAO. Instead you create instances of service with different mixins.


I'm not sure I understood your question properly, but if I did, you're asking how something can inherit without really meaning the same thing as inheriting.

Mixins, however, aren't inheritance – it's actually more similar to dynamically adding a set of methods into an object. Whereas inheritance says "This thing is a kind of another thing", mixins say, "This object has some traits of this other thing." You can see this in the keyword used to declare mixins: trait.

To blatantly steal an example from the Scala homepage:

abstract class Spacecraft {
  def engage(): Unit
}
trait CommandoBridge extends Spacecraft {
  def engage(): Unit = {
    for (_ <- 1 to 3)
      speedUp()
  }
  def speedUp(): Unit
}
trait PulseEngine extends Spacecraft {
  val maxPulse: Int
  var currentPulse: Int = 0
  def speedUp(): Unit = {
    if (currentPulse < maxPulse)
      currentPulse += 1
  }
}
class StarCruiser extends Spacecraft
                     with CommandoBridge
                     with PulseEngine {
  val maxPulse = 200
}

In this case, the StarCruiser isn't a CommandoBridge or PulseEngine; it has them, though, and gains the methods defined in those traits. It is a Spacecraft, as you can see because it inherits from that class.

It's worth mentioning that when a trait extends a class, if you want to make something with that trait, it has to extend that class. For example, if I had a class Dog, I couldn't have a Dog with PulseEngine unless Dog extended Spacecraft. In that way, it's not quite like adding methods; however, it's still similar.


A trait (which is called mixin when mixed with a class) is like an interface in Java (though there are many differences) where you can add additional features to a class without necessarily having "is a" relationship. Or you can say that generally traits bundle up features which can be used by multiple independent classes.

To give you an example from Scala library, Ordered[A] is a trait which provides implementation for some basic comparison operations (like <, <=, >, >=) to classes that can have data with natural ordering.

For example, let's say you have your own class Number and subclasses EvenNumber and OddNumber as shown below.

class Number(val num : Int) extends Ordered[Number] {
  override def compare(that : Number) = this.num - that.num
}

trait Half extends Number {
  def half() = num / 2
}

trait Increment extends Number {
  def increment() = num + 1
}

class EvenNumber(val evenNum : Int) extends Number(evenNum) with Half

class OddNumber(val oddNum : Int) extends Number(oddNum) with Increment

In the example above, classes EvenNumber and OddNumber share is a relationship with Number but EvenNumber does not have "is a" relation with Half neither OddNumber share "is a" relation with Increment.

Another important point is even though class Number uses extends Ordered syntax, it means that Number has an implicit is a relationship with superclass of Ordered ie Any.

Tags:

Oop

Scala