Multiple inheritance: playing God…

One of Scala’s main features is the possibility of doing mixin. By using mixin, we can have multiple inheritance from several traits. Traits? Mixin? What the …? Well, step by step 🙂

What are traits?

Traits (rasgos for those of you trying to learn Cervantes’ mother tongue) are a bundling of attributes and methods that define a feature o characteristic. They’re similar to Java’s interfaces, except traits can be implemented partially, that is, with only some of its methods or values defined.

They are used to add behaviours to other entities. For instance, let’s implement the trait CanFly, in which we’ll define the values and methods that all flying creatures must conform to:


trait CanFly {

  val altitude: Float

  def fly() = println("I'm flying!!!")
}

As can be observed, this trait contains an undefined variable altitude and a defined method fly. We can create an instance from this trait by using an anonymous class:


val myFlyingAnimal = new CanFly {}

However, given that altitude variable is undefined, this piece of code will result in a compile time error. So, for a trait to be instantiated, all values and methods have to be implemented:


val myFlyingAnimal = new CanFly { val altitude = 100.0f }

 

How can tratis be used?

Although we now know how to instantiate traits by means of anonymous classes, to be fair it is not one of its most common applications.

As we said before, traits are used to add behaviours to our entities. And that can be done by using composition, by mixin one or multiple traits when defining a different trait, a class, a case class…

In order to do so, two reserved words are used: strong>extends and with. The first trait from which we inherit will be preceded by extends word, the rest will be preceded by with.


case class Pigeon extends CanFly

case class Superman extends Superhero with CanFly

 

nlY1Wxv

This is what we call Mixin. Now it all makes much more sense, doesn’t it?

How do traits work when facing the diamond problem?

Firstly, let’s create an scenario with this ambiguity. On one hand, we have an Animal trait, with a non-implemented method that returns the sound produced by the animal.


trait Animal {
  def sound: String
}

On the other hand, we also have two specifications of an animal: a cat and a dog.


trait Cat extends Animal {
  override def sound = "Meow"
}

trait Dog extends Animal {
  override def sound = "Woof"
}

Now, by using our boundless imagination, let’s think of a fox as a mixture between a cat and a dog.


case class Fox extends Cat with Dog

But, if we try to print the sound of our fox…


val myFox = Fox()
println(myFox.sound)

 

nlY1Wxv

 

Well, in this case, our fox will bark. Why? Because the last trait that’s been used in the mixin is Dog. At first, Cat implementation is applied, but then it is overwritten by the following trait that is defined, that is, Dog. So we can say that traits are instantiated in the same order they are declared.

And that’s all! What have we learnt today? That traits and mixin are pretty useful… and that sometimes, foxes say ‘woof’!

Anuncios

One thought on “Multiple inheritance: playing God…

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s