This code in Java compiles without errors:
interface T {
interface Q {
}
}
class C implements T.Q {
}
whereas this code in Scala does not:
trait T {
trait Q {
}
}
class C extends T.Q {
}
What is the correct translation (if it exists) of the Java code listing into Scala?
Theoretical explanations about language design are welcome.
Like a class, Traits can have methods(both abstract and non-abstract), and fields as its members. Traits are just like interfaces in Java. But they are more powerful than the interface in Java because in the traits we are allowed to implement the members.
Scala also allows traits to be partially implemented but traits may not have constructor parameters.
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.
Traits are like interfaces in Java.
The inner type Q
is defined only for specific instance implementation of the T
trait. Since scala has path-dependent types, each instance of T
will have his own subtrait Q
.
scala> trait T {
| trait Q
| }
defined trait T
scala> class C extends T {
| def getQ: this.Q = new this.Q {}
| }
defined class C
scala> val inC = (new C).getQ
inC: C#Q = C$$anon$1@3f53073a
scala> val c = new C
c: C = C@1a7e4ff0
scala> new c.Q {}
res4: c.Q = $anon$1@36bbb2f5
If you need an interface for a generic behavior for your clients to implement, and not dependent on a specific C
instance, you should define it within an Object
scala> object T {
| trait Q {
| def implementMe: Unit
| }
| }
defined module T
scala> val inT = new T.Q {
| def implementMe = println("implemented!")
| }
inT: T.Q = $anon$1@20f2a08b
scala> inT.implementMe
implemented!
Why path-dependent types?
As for the design reasons, look here
You cannot do that. When types are nested you're creating what is called a path-dependent type, meaning the type of each instance of the inner entity is tied to the specific instance within which it's constructed.
In other words, you interface Q has no independent existence that would allow you to refer to it apart from an instance of T.
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