繁体   English   中英

了解标记的类型和asInstanceOf

[英]Understanding Tagged Types and asInstanceOf

我使用Miles Sabin gist标记的类型:

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

我的问题是:如何? 这怎么不会抛出ClassCastexceptions.asInstanceOf[String @@ MyTrait] 从我的角度来看, "lala"是String类型的,而不是String with { type Tag = MyTrait}类型的String with { type Tag = MyTrait}因为它像通常的String对象一样被实例化。 asInstanceOf方法的神奇之处是什么?

首先,请注意,标记类型的全部目的是为了避免运行时开销,但这也意味着您不能指望运行时类型检查可用于区分它们!

asInstanceOf是一个运行时asInstanceOf类型转换,并且JVM不知道Scala类型系统(甚至Java)。 它只有类,接口和基元。 因此, asInstanceOf只能转换为已擦除类型,即与Scala类型最接近的JVM等效项。 String with { type Tag = MyTrait}String擦除类型为String ,因此成功。

规范的相关部分是:

  1. 标准库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() } 
  2. 类型模式说明了x: String with { type Tag = MyTrait }是如何匹配的:

    非上述形式之一的类型也被接受为类型模式。 但是,这些类型模式将转换为它们的擦除。 Scala编译器将对这些模式发出“未经检查”的警告,以标记可能丢失类型安全性。

  3. 最后

    T1 with … with Tn {R}擦除T1 with … with Tn {R}的复合类型T1 with … with Tn {R}就是T1,…,Tn的交点控制符的擦除。

    在这种情况下, T1StringT2AnyRef { type Tag = MyTrait } ,因此您将获得StringAnyRef的交集主导AnyRef ,即String

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM