Anveshan
Anveshan

Reputation: 624

What is the difference between mixins and inheritance?

I am trying to understand the Mixins in the context of scala. In particular I wanted to know difference between concepts of inheritance and Mixins.

The definition of Mixin in wiki says :

A mixin class acts as the parent class, containing the desired functionality. A subclass can then inherit or simply reuse this functionality, but not as a means of specialization. Typically, the mixin will export the desired functionality to a child class, without creating a rigid, single "is a" relationship. Here lies the important difference between the concepts of mixins and inheritance, in that the child class can still inherit all the features of the parent class, but, the semantics about the child "being a kind of" the parent need not be necessarily applied.

In the above definition, I am not able to understand the statements marked in bold. what does it mean that

  1. A subclass can inherit functionality in mixin but not as a means of specialization
  2. In mixins, the child inherits all features of parent class but semantics about the child "being a kind" the parent need not be necessarily applied. - How can a child extend a parent and not necessarily a kind of Parent ? Is there an example like that.

Upvotes: 22

Views: 10312

Answers (5)

rogertangdq
rogertangdq

Reputation: 21

The difference between mixin and inheritance is at semantic level. At syntax level they all are the same.

To mix in a trait, or to inherit from a trait, they all use extends or with which is the same syntax.

At semantic level, a trait that is intended to be mixed in usually doesn't have a is a relationship with the class mixining it which differs to a trait that is intended to be inherited.

To me, whether a trait is a mixin or parent is very subjective, which often time is a source of confusion.

Upvotes: 2

Som Bhattacharyya
Som Bhattacharyya

Reputation: 4112

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.

Upvotes: 4

anon
anon

Reputation:

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.

Upvotes: 22

justAbit
justAbit

Reputation: 4256

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.

Upvotes: 5

mvd
mvd

Reputation: 2720

I think it is talking about the actual class hierarchy. For example, a Dog is a type of Animal if it extends from the class (inheritance). It can be used wherever an Animal parameter is applicable.

Upvotes: 1

Related Questions