Обращаясь к типу внутреннего класса в Scala
Следующий код пытается подражать Полиморфное встраивание 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: Inner Classes, мне кажется, что проблема заключается в том, что useInner
ожидает в качестве аргумента экземпляр Inner
из конкретного экземпляра Outer
.
Какое истинное объяснение и как решить эту проблему?
Ответы
Ответ 1
Я предполагаю, что тип 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)
Ответ 2
Проблема заключается в том, как вы описываете, что useInner
ожидает Inner
конкретного экземпляра Outer
. Поскольку enclosing
возвращает общий Outer
, не существует способа связать обе вместе, что я знаю.
Вы можете заставить его, однако:
def toBoolean(x: Outer#Inner): Boolean = {
val outer = x.enclosing
outer.useInner(x.asInstanceOf[outer.Inner])
}
Ответ 3
Вы также можете определить свой член следующим образом:
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
}