The following code tries to mimic Polymorphic Embedding of DSLs: rather than giving the behavior in Inner
, it is encoded in the useInner
method of its enclosing class. I added the enclosing
method so that user has only to keep a reference to Inner
instances, but can always get their enclosing instance. By doing this, all Inner
instances from a specific Outer
instance are bound to only one behavior (but it is wanted here).
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)
It does not compile and scala 2.8 complains about:
type mismatch; found: sandbox.Outer#Inner
required: _81.Inner where val _81:sandbox.Outer
From Programming Scala: Nested c开发者_运维问答lasses and A Tour of Scala: Inner Classes, it seems to me that the problem is that useInner
expects as argument an Inner
instance from a specific Outer
instance.
What is the true explanation and how to solve this problem ?
I suppose the type Inner is like the type this.Inner. Outer#Inner is independent of the outer instance (not a path-dependent type).
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)
The problem is as you describe, that useInner
is expecting an Inner
of a specific Outer
instance. Since enclosing
returns a generic Outer
, there is really no way to tie both together that I know of.
You can force it, however:
def toBoolean(x: Outer#Inner): Boolean = {
val outer = x.enclosing
outer.useInner(x.asInstanceOf[outer.Inner])
}
You can also define your member like this:
def useInner(x:Outer#Inner) : Boolean
Or you can write like this:
abstract class Outer {
class InnerImpl {
def enclosing = Outer.this
}
final type Inner = Outer#InnerImpl
def useInner(x:Inner) : Boolean
}
精彩评论