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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With