2010-02-02 13 views
13

Il seguente codice prova a imitare Polymorphic Embedding of DSLs: anziché dare il comportamento in Inner, è codificato nel metodo useInner della sua classe di inclusione. Ho aggiunto il metodo enclosing in modo che l'utente debba solo mantenere un riferimento alle istanze Inner, ma può sempre ottenere l'istanza che le include. In questo modo, tutte le istanze Inner da un'istanza specifica Outer sono associate a un solo comportamento (ma è necessario qui).Riferendosi al tipo di una classe interna in 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) 

E non compila e Scala 2.8 si lamenta:

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

Da Programming Scala: Nested classes e A Tour of Scala: Inner Classes, mi sembra che il problema è che useInner aspetta come argomento una Inner istanza da una specifica Outer un'istanza .

Qual è la vera spiegazione e come risolvere questo problema?

risposta

16

Suppongo che il tipo Interno sia simile al tipo this.Inner. Esterno # L'interno è indipendente dall'istanza esterna (non un tipo dipendente dal percorso).

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

E 'possibile modificare in Booleano invece di useInner? –

+0

Se provato 'def aBoolean (x: y.Inner forSome {val y: Outer}): Boolean = x.enclosing.useInner (x)' (Tipi esistenziali - Quantificazione esistenziale su valori dal riferimento Scala) ma non lavoro. –

4

Il problema è come lei, che useInner si aspetta una Inner di una specifica istanza Outer. Dal enclosing restituisce un generico Outer, non c'è davvero alcun modo di legare entrambi insieme che io conosca.

È possibile forzare, però:

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

È possibile anche definire il membro in questo modo:

def useInner(x:Outer#Inner) : Boolean 

Oppure si può scrivere in questo modo:

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