Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing inner traits in Scala like we do with inner interfaces in Java

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 image 798
gd1 Avatar asked Mar 25 '13 12:03

gd1


People also ask

Is trait in Scala same as interface in Java?

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.

Can traits have implementation Scala?

Scala also allows traits to be partially implemented but traits may not have constructor parameters.

Is trait an 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.

Which of the following features in Java resembles a trait in Scala?

Traits are like interfaces in Java.


2 Answers

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

like image 67
pagoda_5b Avatar answered Nov 05 '22 15:11

pagoda_5b


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.

like image 44
Randall Schulz Avatar answered Nov 05 '22 15:11

Randall Schulz