Home > database >  Concept of Linearization in Scala and behaviour of super
Concept of Linearization in Scala and behaviour of super

Time:07-11

Consider the following example of traits:

trait TextileEngineer extends Engineer {
  override def nameIt = {println("TextileEngineer"); super.nameIt;}
}
trait FabricEngineer extends Engineer {
  override def nameIt = {println("FabricEngineer"); super.nameIt;}
}

trait Engineer extends Person {
  override def nameIt = {println("Engineer"); super.nameIt;}
}
trait ClothMaker extends Trader {
  override def nameIt = {println("ClothMaker"); super.nameIt;}
}
trait Trader {
  def nameIt = println("Trader");
}

trait Parent extends Person with Human {
  override def nameIt = {println("Parent"); super.nameIt;}
}
trait Person extends Human {
  override def nameIt = {println("Person"); super.nameIt;}
}
trait Human {
  def nameIt = {println("Human");}
}

object Linear extends App {
  val data = new TheSmiths {}
  data.nameIt
}

trait TheSmiths extends FabricEngineer with TextileEngineer with ClothMaker with Parent {
  override def nameIt: Unit = super[TextileEngineer].nameIt //-----------override:1
  override def nameIt: Unit = super[FabricEngineer].nameIt //------------override:2
  override def nameIt: Unit = super.nameIt //------------override:3
}
  • when in the final trait - the override:1 is used - the output is -
TextileEngineer
FabricEngineer
Engineer
Person
Human
  • but when override:2 is used - the answer is -
FabricEngineer
Engineer
Person
Human
  • But when the override:3 is used - the answer is - Why is the hierarchy not followed upto the Human when the trait Parent is the part of other hierarchy?
Parent
ClothMaker
Trader

CodePudding user response:

The short answer:

Because Trader does not call super inside nameIt:

trait Trader {
  def nameIt = println("Trader");
}

The long answer:

Linearization begins with TheSmiths itself, then checks every class or trait it inherits from, starting from the rightmost extended trait to the leftmost extended trait (or class if you extend one), but in a depth-first search manner.

So for example, your linearization of TheSmiths is:

TheSmiths -> Parent -> Person -> Human -> ClothMaker -> Trader -> TextileEngineer -> 
Engineer -> Person -> Human -> FabricEngineer -> Engineer -> Person -> Human

Now duplicates (which indicate a diamond problem) are eliminated leaving the last occurrence of every type in the list. So the actual linearization of TheSmiths becomes:

TheSmiths -> Parent -> ClothMaker -> Trader -> TextileEngineer -> FabricEngineer -> 
Engineer -> Person -> Human

This is the linearization that occurs when you instantiate TheSmiths using new.

Then, whenever you call super inside one of those classes, the invoked method is the next one up the chain. If all of the methods but the last one call super, the net result is stackable behavior.

This linearization also serves as a way of verifying the output of the 2 other examples you gave.

  • Related