7

Traits: The Scala Way of Multiple Inheritance

 2 years ago
source link: https://blog.knoldus.com/traits-the-scala-way-of-multiple-inheritance/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Reading Time: 3 minutes

Hi community, in this blog we are gonna talk about the Traits and how Scala Traits can help you while performing multiple inheritances.

What are Traits?

Scala does not allow the concept of multiple inheritances for more than one class, so to do multiple inheritances Scala uses Traits

A trait is a fundamental unit of code reuse in Scala. A trait holds the definitions of method and field, which can be reused when mixing traits into classes. One thing to notice over here is that a class can be mixed with any number of traits which makes traits more powerful than class inheritance.

A simple definition of trait Printer

trait Printer {
  def print(msg : String) = println (msg)
}

Mixing trait into a Class

Traits can be mixed with classes using extend keywords and hence the methods inherited from a trait can be used just like methods inherited from a superclass. Let’s see how this work

trait Printer {
  def print(msg : String) = println(msg)
}

class CustomerPrint extends Printer {
  override def print(msg: String): Unit ={
    println("You have learned trait in this blog")
    super.print(msg)
  }
}

object Main{
  def main(args: Array[String]): Unit = {
    new CustomerPrint().print("End of your printing")
  }
}
Output: You have learned trait in this blog
        End of your printing

If you wish to mix a trait into a class that explicitly extends a super-class, you use extends to indicate the super-class and with to mix in the trait. For example

trait Printer {
  def print(msg : String) = println(msg)
}

class Content{
  def contentPrint(): Unit = {
    println("Scala is a hybrid language")

  }
}

class CustomerPrint extends Content with Printer {
  override def print(msg: String): Unit ={
    println("You have learned trait in this blog")
    super.print(msg)
  }
}

object Main{
  def main(args: Array[String]): Unit = {
    val finalPrint = new CustomerPrint
    finalPrint.contentPrint()
    finalPrint.print("End of your Printing")
  }
}
Output: Scala is a hybrid language
        You have learned trait in this blog
        End of your Printing

Why not Multiple Inheritance?

As we all know that multiple inheritances are subject to the diamond problem. Diamond in computer science refers to the class inheritance diagram and it looks like this:

What’s the problem?

So we have four class A, B, C, and D from which A is a super-class, both B and C are child class which inherits from A and which is absolutely legal but when we go down to class D which inherits from child classes B and C which is not possible or it’s illegal and this is where the problem lies.

Let’s suppose that super-class A contains a method inside it and when our child classes(B & C) inherits from A they have the ability to override the method present inside A, but let’s just say that D tries to inherit from B & C and tries to override the method that is already overwritten in super-class A.

Hence the class D will get confused and it won’t know which method to override cause it might be the case that they’re pretty much the same method and also you can’t write two methods with the same name and this is what the Diamond problem is.

How to solve this problem?

Scala solves this problem with the help of Trait, as we already talked about above that Traits are more flexible than interfaces and can include methods too. Let’s take an example

trait Printer {
  def print(msg : String) = println (msg)
}

trait PrintHyphen extends Printer {
  override def print(msg : String) {
    println("-------------")
    super.print(msg)
  }
}

trait PrintStar extends Printer  {
  override def print(msg : String) {
    println("*************")
    super.print(msg)
  }
}

class Printing extends Printer with PrintHyphen with PrintStar

object CustomPrint {
  def main(args: Array[String]): Unit = {
    new Printing().print("Solving Diamond Problem")
  }
}
Output: *************
        -------------
        Solving Diamond Problem

In the above code class Printing is inheriting from both the traits PrintHyphen and PrintStar which in turn is inheriting from trait Printer and also the output shows the order in which the methods are executed.

When super is used to invoke methods in the above trait example linearization rule come into play to decide call hierarchy. Linearization order for Printing will be:

Conclusion

Thank you guys for making it to the end of my blog, hoping that you must have gained slight knowledge of the Scala trait, how traits work and how to use them in several common idioms.

You saw that traits are similar to multiple inheritances, but because they interpret super using linearization, they both avoid some of the difficulties of traditional multiple inheritances and allow you to stack behaviors, in order to get more knowledge of Scala trait you can refer to the link given below.

References

https://www.artima.com/pins1ed/traits.html

https://docs.scala-lang.org/tour/traits.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK