Oto kilka informacji na temat tego, co dzieje się za sceną. Rozważmy następujący kod:
class Test {
new Object match { case x: Seq[Int] => true }
new Object match { case Seq(1) => true }
}
Jeśli skompilować z scalac -Xprint:12 -unchecked
zobaczysz kod tuż przed fazą skasowaniem (id 13). Dla pierwszego typu wzoru, zobaczysz coś takiego:
<synthetic> val temp1: java.lang.Object = new java.lang.Object();
if (temp1.isInstanceOf[Seq[Int]]())
dla wzoru Seq
odprowadzającej, zobaczysz coś takiego:
<synthetic> val temp3: java.lang.Object = new java.lang.Object();
if (temp3.isInstanceOf[Seq[A]]()) {
<synthetic> val temp4: Seq[A] = temp3.asInstanceOf[Seq[A]]();
<synthetic> val temp5: Some[Seq[A]] = collection.this.Seq.unapplySeq[A](temp4);
// ...
}
w obu przypadkach, nie jest typem sprawdź, czy obiekt jest typu Seq
(Seq[Int]
i Seq[A]
). Parametry typu zostaną wyeliminowane podczas fazy wymazywania. Tak więc ostrzeżenie. Mimo że druga może być nieoczekiwana, sensowne jest sprawdzenie typu, ponieważ jeśli obiekt nie jest typu Seq
, klauzula nie będzie zgodna, a JVM może przejść do następnej klauzuli. Jeśli typ jest zgodny, to obiekt można odrzucić do Seq
i unapplySeq
można wywołać.
RE: komentarz thoredge na sprawdzanie typu. Być może mówimy o różnych rzeczach. Ja po prostu mówiąc, że:
(o: Object) match {
case Seq(i) => println("seq " + i)
case Array(i) => println("array " + i)
}
przekłada się na coś takiego:
if (o.isInstanceOf[Seq[_]]) { // type check
val temp1 = o.asInstanceOf[Seq[_]] // cast
// verify that temp1 is of length 1 and println("seq " + temp1(0))
} else if (o.isInstanceOf[Array[_]]) { // type check
val temp1 = o.asInstanceOf[Array[_]] // cast
// verify that temp1 is of length 1 and println("array " + temp1(0))
}
Kontrola typ jest używany tak, że gdy obsada odbywa się tam nie jest wyjątkiem klasy obsada.
czy ostrzeżenie non zmienna typu argumentu A na typ wzoru seq [A] jest zaznaczone, ponieważ jest on wyeliminowany przez skasowaniem jest uzasadnione i czy nie byłoby sprawy, w których mogłoby istnieć wyjątek klasa obsada nawet z sprawdź typ, nie wiem.
Edycja: tutaj jest przykład:
object SeqSumIs10 {
def unapply(seq: Seq[Int]) = if (seq.sum == 10) Some(seq) else None
}
(Seq("a"): Object) match {
case SeqSumIs10(seq) => println("seq.sum is 10 " + seq)
}
// ClassCastException: java.lang.String cannot be cast to java.lang.Integer
Na ciekawą notatkę, Scala Wersja 2.8.1 nie daje tego ostrzeżenia w tym przypadku – thoredge
@thoredge, domyślam się, że ostrzeżenie w wersji 2.9.0 było prawdopodobnie poprawą. Nie wiem, czy ten konkretny przypadek został przewidziany. – huynhjl