Ссылаясь на тип внутреннего класса в Scala - PullRequest
13 голосов
/ 02 февраля 2010

Следующий код пытается имитировать Полиморфное встраивание DSL : вместо того, чтобы задавать поведение в Inner, он кодируется в методе useInner своего включающего класса. Я добавил метод enclosing, чтобы пользователь мог хранить только ссылку на экземпляры Inner, но всегда мог получить включающий его экземпляр. Таким образом, все Inner экземпляры из конкретного Outer экземпляра привязаны только к одному поведению (но здесь это необходимо).

abstract class Outer {
  sealed class Inner {
    def enclosing = Outer.this
  }
 def useInner(x:Inner) : Boolean
}

def toBoolean(x:Outer#Inner) : Boolean = x.enclosing.useInner(x)

Не компилируется и scala 2.8 жалуется на:

type mismatch; found: sandbox.Outer#Inner
               required: _81.Inner where val _81:sandbox.Outer

Из Программирование Scala: вложенные классы и Тур по Scala: Внутренние классы , мне кажется, что проблема в том, что useInner ожидает в качестве аргумента экземпляр Inner из определенного экземпляра Outer.

Каково истинное объяснение и как решить эту проблему?

Ответы [ 3 ]

16 голосов
/ 02 февраля 2010

Полагаю, тип Inner похож на тип this.Inner.Outer # Inner не зависит от внешнего экземпляра (не зависит от пути).

abstract class Outer {
  sealed class Inner {
    def enclosing = Outer.this
  }
  def useInner(x:Outer#Inner) : Boolean
}

def toBoolean(x:Outer#Inner) : Boolean = x.enclosing.useInner(x)
4 голосов
/ 02 февраля 2010

Проблема, как вы описываете, заключается в том, что useInner ожидает Inner конкретного Outer экземпляра. * * * * * * * * * * * * * * * * * * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 100,

Вы можете заставить его, однако:

def toBoolean(x: Outer#Inner): Boolean = {
  val outer = x.enclosing
  outer.useInner(x.asInstanceOf[outer.Inner])
}
0 голосов
/ 10 апреля 2010

Вы также можете определить своего члена следующим образом:

def useInner(x:Outer#Inner) : Boolean

Или вы можете написать так:

abstract class Outer {
    class InnerImpl {
        def enclosing = Outer.this
    }
    final type Inner = Outer#InnerImpl
    def useInner(x:Inner) : Boolean
}
...