Ответ 1
Вот некоторые сведения о том, что происходит за сценой. Рассмотрим этот код:
class Test {
new Object match { case x: Seq[Int] => true }
new Object match { case Seq(1) => true }
}
Если вы скомпилируете scalac -Xprint:12 -unchecked
, вы увидите код перед фазой стирания (id 13). Для шаблона первого типа вы увидите что-то вроде:
<synthetic> val temp1: java.lang.Object = new java.lang.Object();
if (temp1.isInstanceOf[Seq[Int]]())
Для шаблона выделения Seq
вы увидите что-то вроде:
<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);
// ...
}
В обоих случаях существует тип теста, чтобы увидеть, имеет ли объект тип Seq
(Seq[Int]
и Seq[A]
). Параметры типа будут удалены во время фазы стирания. Таким образом, предупреждение. Несмотря на то, что второе может быть неожиданным, имеет смысл проверить тип, поскольку, если объект не имеет тип Seq
, это предложение не будет соответствовать, и JVM может перейти к следующему разделу. Если тип соответствует, то объект может быть отправлен в Seq
и unapplySeq
может быть вызван.
RE: комментарий thoredge для проверки типа. Может быть, мы говорим о разных вещах. Я просто говорил, что:
(o: Object) match {
case Seq(i) => println("seq " + i)
case Array(i) => println("array " + i)
}
переводит на что-то вроде:
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))
}
Проверка типа используется так, чтобы при выполнении броска исключалось исключение класса.
Является ли предупреждение non variable type-argument A в шаблоне типа Seq [A] непроверенным, поскольку оно устранено стиранием, является оправданным и будут ли случаи, когда может быть исключение класса, отличное от проверки типа, я не делаю Не знаю.
Изменить: вот пример:
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