Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need traits in scala?

Tags:

scala

traits

So, I was trying to make a finagle server, talk to sentry (not important), and stumbled upon a case, where I needed to inherit from two classes (not traits) at the same time, let's call them class SentryHandler extends Handler and class TwitterHandler extends Handler, and assume, that I need to create MyHandler, that inherits from both of them.

After a moment of stupidity, when I thought it was impossible without using a dreaded "delegation pattern", I found a solution:

trait SentryTrait extends SentryHandler
class MyHandler extends TwitterHandler with SentryTrait

Now, this got me thinking: what is the purpose of having the notion of "trait" to being with? If the idea was to enforce that you can inherit from multiple traits but only a single class, it seems awfully easy to get around. It kinda sounds like class is supposed to be the "main" line of inheritance (that you "extend a class with traits", but that isn't true either: you can extend a trait with (or without) a bunch of other traits, and no class at all.

You cannot instantiate a trait, but the same holds for an abstract class ...

The only real difference I can think of is that a trait cannot have constructor parameters. But what is the significance of that? I mean, why not? What would the problem with something like this?

class Foo(bar: String, baz: String) extends Bar(bar) with Baz(baz) 
like image 394
Dima Avatar asked Mar 18 '16 11:03

Dima


People also ask

Why do we need traits?

Traits can define both static members and static methods. It helps developers to reuse methods freely in several independent classes in different class hierarchies. Traits reduces the complexity, and avoids problems associated with multiple inheritance and Mixins.

What is traits in Scala?

A Trait is a concept pre-dominantly used in object-oriented programming, which can extend the functionality of a class using a set of methods. Traits are similar in spirit to interfaces in Java programming language. Unlike a class, Scala traits cannot be instantiated and have no arguments or parameters.

What is the difference between trait and interface in Scala?

Traits in Scala have a lot of similarities with interfaces in Java, but a trait is more powerful than an interface because it allows developers to implement members within it. The trait is a combination of abstract and non-abstract methods. Trait can not be instantiated, thus it has no parameters.

Can traits have implementation Scala?

In Scala, we are allowed to implement the method(only abstract methods) in traits. If a trait contains method implementation, then the class which extends this trait need not implement the method which already implemented in a trait.


1 Answers

Your solution (if I understood correctly) - doesn't work. You cannot multiinherit classes in scala:

scala> class Handler
defined class Handler

scala> class SentryHandler extends Handler
defined class SentryHandler

scala> class TwitterHandler extends Handler
defined class TwitterHandler

scala> trait SentryTrait extends SentryHandler
defined trait SentryTrait

scala> class MyHandler extends TwitterHandler with SentryTrait
<console>:11: error: illegal inheritance; superclass TwitterHandler
 is not a subclass of the superclass SentryHandler
 of the mixin trait SentryTrait
       class MyHandler extends TwitterHandler with SentryTrait

As for the question - why traits, as I see it, this is because traits are stackable in order to solve the famous diamond problem

  trait Base { def x: Unit = () }
  trait A extends Base { override def x: Unit = { println("A"); super.x}}
  trait B extends Base { override def x: Unit = { println("B"); super.x}}

  class T1 extends A with B {}
  class T2 extends B with A {}

  (new T1).x  // Outputs B then A
  (new T2).x  // Outputs A then B

Even though trait A super is Base (for T1) it calls B implementation rather then Base. This is due to trait linearization

So for classes if you extend something - you can be sure that this base will be called next. But this is not true for traits. And that's probably why you do not have trait constructor parameters

like image 92
Archeg Avatar answered Nov 15 '22 03:11

Archeg