Реализация внутренних черт в Scala, как мы делаем с внутренними интерфейсами в Java
Этот код в Java компилируется без ошибок:
interface T {
interface Q {
}
}
class C implements T.Q {
}
тогда как этот код в Scala не имеет:
trait T {
trait Q {
}
}
class C extends T.Q {
}
Каков правильный перевод (если он существует) листинга Java-кода в Scala?
Теоретические объяснения языкового дизайна приветствуются.
2 ответа
Внутренний тип Q
определяется только для конкретной реализации экземпляра T
черта характера. Поскольку у scala есть зависимые от пути типы, каждый экземпляр T
будет иметь свое собственное вычитание 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
Если вам нужен интерфейс для универсального поведения для ваших клиентов, чтобы реализовать, и не зависит от конкретного C
Например, вы должны определить его в 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!
Почему пути-зависимые типы?
Что касается дизайна, посмотрите здесь
Тебе этого не сделать. Когда типы вложены, вы создаете так называемый зависимый от пути тип, то есть тип каждого экземпляра внутренней сущности привязан к конкретному экземпляру, в котором он построен.
Другими словами, ваш интерфейс Q не имеет независимого существования, которое позволило бы вам ссылаться на него отдельно от экземпляра T.