2014-04-29 13 views
6

Mam następujący kod:Scala „nie bierze parametry”, gdy wzorzec-parametrycznego dopasowania case-klasa

sealed trait A 

case class B[T](v: T) extends A 
case class C[T](v: T) extends A 

object Test { 
    def swap(a: A): A = a match { 
    case a: B[t] => C[t](a.v) // works! 
    case C[t](v) => B[t](v) // error: C[t] does not take parameters 
    } 
} 

spodziewałbym albo oba przypadki na niepowodzenie lub obu z nich do pracy. Jakie jest znaczenie błędu w drugim przypadku? Czy istnieją parametryczne klasy przypadków destrukcji składni?

Uwaga: W tym przypadku kluczowe znaczenie ma "t". Jeśli był to "T", sprawdzający szukałby go w parametrach typu metody.

+0

Jest tak również w przypadku wyodrębniania dla vals, tj. 'Val C [T] (v) = ...' – ggovan

+0

Tylko po to, aby upewnić się, że rozumiem twój kod ... używasz 't' do reprezentowania typ? Kiedy według konwencji typy są reprezentowane początkową wielką literą? I, aby jeszcze bardziej zmylić, używasz parametru 'v' do przechowywania wartości dla argumentu' v'? Proszę, spraw, żeby twój kod był trochę mniej ... samoodnoszący się. –

+1

@BobDalgleish: Użycie dużej litery dla tego typu spowoduje błąd tutaj, a użycie wiązania 'v' do' a.v' nie wydaje mi się tak straszne. –

Odpowiedz

6

Kiedy robisz a match { case C(v) => ??? }, rzeczywiście nazwać unapply metodę obiektu C towarzysz coś takiego: C.unapply(a) match {Some(v) => ???}

Jest tylko jeden C przedmiot, a nie cała rodzina C[t]. Nie ma obiektu, który można nazwać jako C[Int], więc case C[t](v) => nie ma sensu.

W twoim przykładzie używasz B[t] jako typu, nie jako wzorca, i dlatego to działa. Pamiętaj, że jeśli mecz może się powieść, nic nie dostaniesz w t, z powodu usunięcia tekstu.

Po wywołaniu C[t](a.v), to przede wszystkim, kompilator usuwa wpisać t tak, a po drugie, to jest przepisany na wezwanie do apply metody na obiekcie towarzysz: C.apply[t](a.v). Zauważ, że parametr type znajduje się w wywołaniu metody, a nie w obiekcie.

+0

Obie odpowiedzi uzupełniają się wzajemnie - jest to bardziej szczegółowe, ale jest nieco niejasne na temat usuwania i "dlaczego" B [t] działa w ten sposób. Drugi wyjaśnia faktycznym odniesieniem do zachowania (w odnośniku są przykłady, które ilustrują i wyjaśniają dokładnie, co dzieje się w odniesieniu do wymazywania typu, Której z dwóch odpowiedzi powinienem zaakceptować? – comco

+1

Bardziej szczegółowy/popularny. – ggovan

1

Po prostu, nie jest częścią języka.

Używane w tej pozycji kompilator szuka typu w środowisku, tak jakby był zwykłym typem wielkich liter. Przechwytywanie typu, które próbujesz wykonać, działa tylko w formularzu case o numerze case x:Y[z] => ....

Przechwytywanie typu w ten sposób nie jest dobrze znaną częścią języka i kazało mi pobierać dane do Scala reference document (punkt 8.3). Osobiście uważam to za rozróżnienie między małymi i dużymi literami, nie według mojego upodobania.

W twoim przykładzie t przyjmuje typ Any, ponieważ informacja o typie dla parametru nie jest dostępna z A.

Powiązane problemy