I am wondering what the semantics of using the abstract
keyword in combination with a trait
is.
If the trait does not define any abstract methods, the abstract
keyword does not prevent me from creating an instance:
scala> abstract trait T
defined trait T
scala> new T{}
res0: java.lang.Object with T = $anon$1@12cd927d
On the other hand, if the trait does define an abstract method, I cannot create an instance (without implementing this method of course) no matter if the abstract
keyword is present or not:
scala> abstract trait T { def foo : Unit }
defined trait T
scala> new T{}
<console>:9: error: object creation impossible, since method foo in trait T of type => Unit is not defined
new T{}
^
scala> trait T { def foo : Unit }
defined trait T
scala> new T{}
<console>:9: error: object creation impossible, since method foo in trait T of type => Unit is not defined
new T{}
^
So what is the abstract
keyword in front of a trait
good for?
It has no effect, traits are automatically abstract.
The abstract modifier is used in class definitions. It is redundant
for traits, and mandatory for all other classes which have incomplete
members.
http://www.scala-lang.org/docu/files/ScalaReference.pdf
You're not creating an instance of the trait. Traits can't be instantiated.
You're creating an instance of an anonymous class extending the trait.
In general,
new __t__
is equivalent to
{ class __anonymous__ extends __t__; new __anonymous__ }
(where __anonymous__
is a fresh name of an anonymous class that is inaccessible to the user program).
This is detailed in section 6.10 Instance Creation Expressions of the Scala Language Specification.
So, the reason why you can create an instance in the first case, is because you're not creating an instance of the trait (which is abstract) but an object (which isn't).
In the second case, the reason why you can't create an instance is that if you inherit from something, whether that is a trait or a class, you ultimately have to implement its abstract methods somewhere along the inheritance chain in order to instantiate it. In the first case, there are no abstract methods to implement.
The abstract
keyword itself makes no difference: traits are implicitly abstract, the keyword is redundant.