Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it possible to instantiate multiple traits in Scala, but not a single one?

Let's say we have two traits:

trait Trait1
trait Trait2

If I try something like val single = new Trait1 I get an error error: trait Trait1 is abstract; cannot be instantiated. However, val twoTraits = new Trait1 with Trait2 compiles. Why is it so?

P.S. I also observed that val single = new Trait1 {} compiles just fine. Could you provide a proper explanation?

like image 339
Ivaylo Toskov Avatar asked Feb 23 '17 15:02

Ivaylo Toskov


1 Answers

Technically, you can't instantiate a single trait or multiple mixed traits directly, but the compiler uses some syntactic sugar that allows you to create anonymous classes that extend them. Let's say we have:

trait A
trait B

When you call new A with B, what's really happening is that the compiler is creating an anonymous class that mixes in both A and B. You get:

final class $anon extends A with B
new $anon()

When you call new A {}, the same thing happens. You get an anonymous class that extends A:

final class $anon extends A
new $anon()

The only difference is syntactical. When creating an anonymous class from a single trait, you are required to at least use braces {} to distinguish it from a class. That is, it is easier to discern whether the template can be constructed, or must be wrapped in an anonymous class to be constructed. With multiple traits (or even a class with traits mixed in), the compiler understands it will always need to create an anonymous class first.

To summarize:

class C

new A {}       // Anonymous class that extends A, then constructed
new A with B   // Anonymous class that extends A with B, then constructed
new C          // Constructed instance of class C
new C with A   // Anonymous class that extends C with A, then constructed
like image 135
Michael Zajac Avatar answered Nov 15 '22 04:11

Michael Zajac