2013-08-06 25 views
12

typy ścieżek zależne są użyteczne:Zależne typy nie działają dla konstruktorów?

trait Sys { 
    type Global 
} 
def foo[S <: Sys](system: S)(global: system.Global) =() 

Dlaczego nie działa to dla konstruktorów?

class Foo[S <: Sys](val system: S)(val global: system.Global) 

Czy robię to po prostu źle?

+0

Znalazłem to zdanie w SLS: * Jednak formalny parametr wartości może nie wchodzić w skład żadnej z klas nadrzędnych lub członków szablonu klasy t. * (5.3, p56) dotyczących * formalnego klauzule parametru wartości dla podstawowego konstruktora *. – Beryllium

+4

Obejście: 'cecha Foo [S: senia

+0

@senia Tak, używam teraz cechy, ale metoda konstruktora jest dość brzydka, ale działa. –

Odpowiedz

5

Wydaje mi się, że to błąd. Edytuj: Znalazłem, to jest SI-5712.

Sekcja §5.3 o 2,9 SLS mówi:

(PS1). . . (psn) to formalne parametry wartości dla podstawowego konstruktora klasy . Zakres formalnego parametru wartości obejmuje wszystkie kolejne sekcje parametrów i szablon t.

Istnieje wyjątek:

Jednak parametr formalny wartość nie może stanowić część rodzajów którejkolwiek z klas dominujących lub członków klasy szablonu t.

Ale ona mówi, że nie może być częścią rodzajów dowolnym klas dominujących lub członków, nie stanowi jakiegokolwiek następujących sekcjach parametrów, więc nie wydaje się zabraniać rodzajów ścieżek zależny między grupy argumentów.

Można obejść ten z wtórnym konstruktora:

class Foo[S <: Sys] private[this]() { 
    def this(system: S)(global: system.Global) = this 
} 

Edycja: Ten wtórny konstruktor obejście nie jest bardzo dobra: wystawienie system lub global stać się bardzo trudne, ponieważ tylko podstawowy konstruktor może zadeklarować val s .

Przykładem z obsadą:

class Foo[S <: Sys] private[this]() { 
    private[this] var _system: S = _ 
    private[this] var _global: system.Global = _ 

    def this(system0: S)(global0: system0.Global) = { 
    this 
    _system = system0 
    _global = global0.asInstanceOf[system.Global] 
    } 

    lazy val global: system.Global = _global 
    lazy val system: S = _system 
} 

Ale to jest coraz okropne. Sugestia @ seni jest znacznie lepsza.

+0

Ok. Problem z konstruktorem podrzędnym jest taki, że w ten sposób nie będę w stanie skonstruować 'Foo' mającego' def global: system.Global' (nie próbowałem, ale brzmi to niewiarygodnie) –

+0

Hum, ty "W porządku, nie ma prostego sposobu na ujawnienie tych wartości przez' Foo'. Będziesz potrzebował co najmniej "var" i obsady, co jest trochę smutne, patrz edytuj. – gourlaysama

+1

Dzięki za wykopanie biletu na błąd –