2010-02-02 4 views
13

Le code suivant essaie d'imiter Polymorphic Embedding of DSLs: au lieu de donner le comportement dans Inner, il est codé dans la méthode useInner de sa classe englobante. J'ai ajouté la méthode enclosing de sorte que l'utilisateur n'ait qu'à garder une référence à Inner instances, mais peut toujours obtenir leur instance englobante. En faisant cela, toutes les instances Inner d'une instance spécifique Outer sont liées à un seul comportement (mais c'est voulu ici).Référence au type d'une classe interne dans 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) 

Il ne compile pas et scala 2.8 se plaint:

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

De Programming Scala: Nested classes et A Tour of Scala: Inner Classes, il me semble que le problème est que useInner attend comme argument une instance Inner d'une Outer instance spécifique .

Quelle est la véritable explication et comment résoudre ce problème?

Répondre

16

Je suppose que le type Inner est comme le type this.Inner. L'extérieur # Inner est indépendant de l'instance externe (pas un type dépendant du chemin).

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

Est-il possible modifier toBoolean au lieu de useInner? –

+0

Si essayé 'def toBoolean (x: y.Inner forSome {valy: extérieur}): Boolean = x.enclosing.useInner (x)' (Types existentiels - Quantification existentielle sur les valeurs de la référence Scala) mais il n'a pas travail. –

4

Le problème est que vous décrivez, ce useInner attend un Inner d'une Outer instance spécifique. Depuis enclosing renvoie un générique Outer, il n'y a vraiment aucun moyen d'attacher les deux ensemble que je connais.

Vous pouvez forcer, cependant:

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

Vous pouvez également définir votre député comme celui-ci:

def useInner(x:Outer#Inner) : Boolean 

Ou vous pouvez écrire comme ceci:

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