Путь-зависимость и внутренние классы - PullRequest
0 голосов
/ 08 января 2019

Следующий пример кода не компилируется с ошибкой, указанной ниже.

class Outer {
  class Inner

  val instance: Inner = new Inner

  def verify(pd: Inner): Boolean = pd == instance
}

class UseOuter(val pdp: Outer) {
  def foo: pdp.Inner = pdp.instance
}

class UseCase {
  val pdp = new Outer
  val user = new UseOuter(pdp)

  val i = user.foo

  pdp.verify(i)
}

Ошибка:

test.sc:19: type mismatch;
 found   : UseCase.this.user.pdp.Inner
 required: UseCase.this.pdp.Inner
  pdp.verify(i)
             ^
Compilation Failed

Я не совсем уверен, но чтение Внутренние классы предполагает, что это предполагаемое поведение? Конкретно следующее предложение:

В отличие от Java-подобных языков, где такие внутренние классы являются членами из включающего класса, в Scala такие внутренние классы связаны с внешний объект.

Если это так, и это действительно желаемое поведение, есть ли способ закодировать это требование в Scala?

Есть несколько похожих вопросов, но все они касаются внутренних типов, а не классов, и предложенные решения не будут применяться.

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Вот подход, который поддерживает безопасность зависимых от пути типов в те времена, когда вы этого хотите. Сначала измените UseOuter, чтобы в качестве параметра типа был принят тип pdp:

class UseOuter[O <: Outer](val pdp: O) {
  def foo: pdp.Inner = pdp.instance
}

Затем, когда вы создаете экземпляр UseOuter, явно , передаете pdp.type в качестве параметра типа:

val user = new UseOuter[pdp.type](pdp)

Это позволяет компилятору помнить, что pdp в UseOuter - это то же самое, что pdp в UseCase, поэтому типы совпадают правильно.

0 голосов
/ 08 января 2019

Например, вы можете использовать проекции типа :

class Outer {
  class Inner

  val instance: Inner = new Inner

//  def verify(pd: Inner): Boolean = pd == instance
  def verify(pd: Outer#Inner): Boolean = pd == instance
}

class UseOuter(val pdp: Outer) {
//  def foo: pdp.Inner = pdp.instance
  def foo: Outer#Inner = pdp.instance
}

class UseCase {
  val pdp: Outer = new Outer
  val user: UseOuter = new UseOuter(pdp)

//  val i: user.pdp.Inner = user.foo
  val i: Outer#Inner = user.foo

  pdp.verify(i)
}
...