Вот немного понимания того, что происходит за сценой. Рассмотрим этот код:
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: комментарий к проверке типа. Может быть, мы говорим о разных вещах. Я просто говорил, что:
(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))
}
Проверка типа используется для того, чтобы после того, как приведение завершено, исключений приведения класса не было.
Является ли предупреждение не переменным аргументом типа 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