Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala stackable traits

Tags:

scala

traits

For the code below as I understand it linearization of expression

new E with D with C with B

is E -> C -> B -> D. So then shouldnt the expression d.foo() in the code

below evaluate to ECBD instead of CBDE. What am I missing?

    trait A {
      def foo(): String = ""
    }

    trait B extends A {
      abstract override def foo() = "B" + super.foo()
    }

    trait C extends B {
      abstract override def foo() = "C" + super.foo()
    }

    trait D extends A {
      abstract override def foo() = "D" + super.foo()
    }

    class E extends A{
      override def foo() = "E"
    }

    var d = new E with D with C with B;
    d.foo() //prints CBDE

I have noticed that if I have a class F like below

class F extends A with D with C with B{
      override def foo() = "F" + super.foo()
}

and do

new F().foo

it prints "FCBD"

It seems a bit inconsistent to me because class F is mixed in the same way as the expression but has a different print order

like image 396
Abdul Rahman Avatar asked Nov 13 '16 22:11

Abdul Rahman


People also ask

What is stackable traits pattern in scala?

The stackable traits design pattern is based on mixin composition—something we became familiar with in the early chapters of this book. We usually have an abstract class or a trait that defines an interface, a base implementation, and traits that extend the abstract class to stack modifications on it.

Can scala traits have methods?

In scala, trait is a collection of abstract and non-abstract methods. You can create trait that can have all abstract methods or some abstract and some non-abstract methods. A variable that is declared either by using val or var keyword in a trait get internally implemented in the class that implements the trait.

Can traits be instantiated in scala?

Unlike a class, Scala traits cannot be instantiated and have no arguments or parameters. However, you can inherit (extend) them using classes and objects.

What is a trait Mixins in scala?

In scala, trait mixins means you can extend any number of traits with a class or abstract class. You can extend only traits or combination of traits and class or traits and abstract class. It is necessary to maintain order of mixins otherwise compiler throws an error.


1 Answers

The first case with new E with D with C with B is perfectly explained here. Its linearization is EDBC, so when you call d.foo(), it

  • first calls C#foo(),
  • then B#foo(),
  • then D#foo()
  • and finally E#foo().

If you make E a trait and mix it in the end: val d = new D with C with B with E, then d.foo() will return just "E", because trait E is the "last" in the linearization and just overridesfoo.

The case of F is different, because you define foo as "F" + super.foo(), and super in this case is A with D with C with B whose linearization is ADBC, so new F().foo() - first prints "F", - then its super.foo() which is "CBD".

By the way, try changing A#foo() to return "A", then you will see that in E you override A's foo so "A" doesn't appear in the result, and in F it is "FCBDA".

like image 143
laughedelic Avatar answered Oct 20 '22 04:10

laughedelic