了解标记类型和 asInstanceOf
Understanding Tagged Types and asInstanceOf
我使用来自 Miles Sabin 要点的标记类型:
type Tagged[U] = { type Tag = U }
type @@[T, U] = T with Tagged[U]
trait MyTrait
def tag(s: String): String @@ MyTrait = s.asInstanceOf[String @@ MyTrait]
我可以像这样使用(并且有效):
scala> tag("lala")
res7: @@[String,MyTrait] = lala
我的问题是:如何?这怎么不抛ClassCastexception
:s.asInstanceOf[String @@ MyTrait]
。在我看来,"lala"
是 String 类型但不是 String with { type Tag = MyTrait}
类型,因为它像通常的 String
对象一样被实例化。 asInstanceOf
方法有什么神奇之处?
首先,请注意标记类型的全部意义在于避免运行时开销,但这也意味着您不能指望运行时类型检查能够区分它们!
asInstanceOf
是运行时转换,JVM 不知道 Scala 类型系统(甚至 Java 的);它只有 类、接口和原语。所以 asInstanceOf
只能转换为 erased 类型,即最接近 Scala 类型的 JVM 等价物。 String with { type Tag = MyTrait}
的擦除类型为String
,所以成功。
规范的相关部分是:
Standard Library定义asInstanceOf
如下:
/** Type cast; needs to be inlined to work as given */
def asInstanceOf[A]: A = this match {
case x: A => x
case _ => if (this eq null) this
else throw new ClassCastException()
}
Type patterns解释了x: String with { type Tag = MyTrait }
是如何匹配的:
Types which are not of one of the forms described above are also accepted as type patterns. However, such type patterns will be translated to their erasure. The Scala compiler will issue an "unchecked" warning for these patterns to flag the possible loss of type-safety.
-
The erasure of a compound type T1 with … with Tn {R}
is the erasure of the intersection dominator of T1,…,Tn
.
在这种情况下T1
是String
,T2
是AnyRef { type Tag = MyTrait }
,所以你得到String
和AnyRef
的交集支配符, 即 String
.
我使用来自 Miles Sabin 要点的标记类型:
type Tagged[U] = { type Tag = U }
type @@[T, U] = T with Tagged[U]
trait MyTrait
def tag(s: String): String @@ MyTrait = s.asInstanceOf[String @@ MyTrait]
我可以像这样使用(并且有效):
scala> tag("lala")
res7: @@[String,MyTrait] = lala
我的问题是:如何?这怎么不抛ClassCastexception
:s.asInstanceOf[String @@ MyTrait]
。在我看来,"lala"
是 String 类型但不是 String with { type Tag = MyTrait}
类型,因为它像通常的 String
对象一样被实例化。 asInstanceOf
方法有什么神奇之处?
首先,请注意标记类型的全部意义在于避免运行时开销,但这也意味着您不能指望运行时类型检查能够区分它们!
asInstanceOf
是运行时转换,JVM 不知道 Scala 类型系统(甚至 Java 的);它只有 类、接口和原语。所以 asInstanceOf
只能转换为 erased 类型,即最接近 Scala 类型的 JVM 等价物。 String with { type Tag = MyTrait}
的擦除类型为String
,所以成功。
规范的相关部分是:
Standard Library定义
asInstanceOf
如下:/** Type cast; needs to be inlined to work as given */ def asInstanceOf[A]: A = this match { case x: A => x case _ => if (this eq null) this else throw new ClassCastException() }
Type patterns解释了
x: String with { type Tag = MyTrait }
是如何匹配的:Types which are not of one of the forms described above are also accepted as type patterns. However, such type patterns will be translated to their erasure. The Scala compiler will issue an "unchecked" warning for these patterns to flag the possible loss of type-safety.
-
The erasure of a compound type
T1 with … with Tn {R}
is the erasure of the intersection dominator ofT1,…,Tn
.在这种情况下
T1
是String
,T2
是AnyRef { type Tag = MyTrait }
,所以你得到String
和AnyRef
的交集支配符, 即String
.