2010-02-02 16 views
13

Poniższy kod próbuje naśladować Polymorphic Embedding of DSLs: zamiast podawać zachowanie w Inner, jest kodowany w metodzie otaczającej klasy useInner. Dodałem metodę enclosing, aby użytkownik mógł zachować tylko odniesienia do instancji Inner, ale zawsze może uzyskać ich załączającą instancję. W ten sposób wszystkie instancje z określonej instancji Outer są powiązane tylko z jednym zachowaniem (ale jest to pożądane tutaj).Odwołując się do typu klasy wewnętrznej w Scali

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) 

To nie kompiluje i scala 2,8 narzeka:

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

Od Programming Scala: Nested classes i A Tour of Scala: Inner Classes, wydaje mi się, że problemem jest to, że useInner oczekuje jako argument Inner instancji z konkretnego Outer instancji .

Jakie jest prawdziwe wyjaśnienie i jak rozwiązać ten problem?

Odpowiedz

16

Przypuszczam, że typ Inner jest podobny do typu This.Inner. Zewnętrzne # Wewnętrzne jest niezależne od zewnętrznej instancji (nie jest to typ zależny od ścieżki).

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

Czy to możliwe, zmodyfikować doBoolean zamiast useInner? –

+0

Jeśli próbowano 'def doBoolean (x: y.Inner forSome {val y: Outer}): Boolean = x.enclosing.useInner (x)' (Egzystencjalne typy - Egistential Quantification over Values ​​od odnośnika Scala), ale nie praca. –

4

Problemem jest to, jak można opisać, że useInner spodziewa się Inner konkretnego Outer instancji. Od enclosing zwraca ogólny Outer, tak naprawdę nie ma sposobu, aby powiązać obie te, które znam.

Można go zmusić, jednakże:

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

Można również zdefiniować element tak:

def useInner(x:Outer#Inner) : Boolean 

Albo można napisać tak:

abstract class Outer { 
    class InnerImpl { 
     def enclosing = Outer.this 
    } 
    final type Inner = Outer#InnerImpl 
    def useInner(x:Inner) : Boolean 
} 
Powiązane problemy