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

末鹿安然 提交于 2019-11-30 03:48:37

问题


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.


回答1:


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




回答2:


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.



来源:https://stackoverflow.com/questions/15614849/implementing-inner-traits-in-scala-like-we-do-with-inner-interfaces-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!