2010-02-02 19 views
13

El siguiente código intenta imitar Polymorphic Embedding of DSLs: en lugar de dar el comportamiento en Inner, está codificado en el método useInner de su clase adjunta. Agregué el método enclosing para que el usuario solo tenga que mantener una referencia a las instancias Inner, pero siempre puede obtener su instancia adjunta. Al hacer esto, todas las instancias Inner de una instancia específica Outer están vinculadas a un solo comportamiento (pero se desea aquí).Refiriéndose al tipo de una clase interna en Scala

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) 

No compila y Scala 2.8 se queja de:

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

De Programming Scala: Nested classes y A Tour of Scala: Inner Classes, me parece que el problema es que useInner Espera como argumento una Inner ejemplo de un Outer instancia específica .

¿Cuál es la verdadera explicación y cómo resolver este problema?

Respuesta

16

Supongo que el tipo Inner es como el tipo this.Inner. Outer # Inner es independiente de la instancia externa (no es un tipo dependiente de la ruta).

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) 
+0

¿Es posible para modificar toBoolean en lugar de useInner? –

+0

Si se intentó 'def toBoolean (x: y.Inner forSome {val y: Outer}): Boolean = x.enclosing.useInner (x)' (Tipos Existenciales - Cuantificación Existencial sobre los Valores de la referencia de Scala) pero no lo hizo trabajo. –

4

El problema es que usted describe, que useInner espera un Inner de un Outer instancia específica. Dado que enclosing devuelve un Outer genérico, realmente no hay forma de vincular los dos que conozco.

Puede forzar que, sin embargo:

def toBoolean(x: Outer#Inner): Boolean = { 
    val outer = x.enclosing 
    outer.useInner(x.asInstanceOf[outer.Inner]) 
} 
0

También puede definir su miembro de la siguiente manera:

def useInner(x:Outer#Inner) : Boolean 

o puede escribir así:

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