Реализация внутренних черт в 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.

Другие вопросы по тегам