简体   繁体   English

了解标记的类型和asInstanceOf

[英]Understanding Tagged Types and asInstanceOf

I use tagged types from Miles Sabin gist: 我使用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]

Which I can use like this (and it works): 我可以这样使用(并且可以使用):

scala> tag("lala")
res7: @@[String,MyTrait] = lala

My question is: how? 我的问题是:如何? How doesn't this throw ClassCastexception : s.asInstanceOf[String @@ MyTrait] . 这怎么不会抛出ClassCastexceptions.asInstanceOf[String @@ MyTrait] From my point of view, "lala" is of type String but not of type String with { type Tag = MyTrait} since it was instantiated like usual String object. 从我的角度来看, "lala"是String类型的,而不是String with { type Tag = MyTrait}类型的String with { type Tag = MyTrait}因为它像通常的String对象一样被实例化。 What is the magic with asInstanceOf method? asInstanceOf方法的神奇之处是什么?

First, note that the whole point of tagged types is to avoid runtime overhead, but this also means you can't expect runtime type checks to work for distinguishing them! 首先,请注意,标记类型的全部目的是为了避免运行时开销,但这也意味着您不能指望运行时类型检查可用于区分它们!

asInstanceOf is a runtime cast, and JVM doesn't know the Scala type system (or even Java's); asInstanceOf是一个运行时asInstanceOf类型转换,并且JVM不知道Scala类型系统(甚至Java)。 it only has classes, interfaces, and primitives. 它只有类,接口和基元。 So asInstanceOf can only cast to the erased type, ie the closest JVM equivalent of the Scala type. 因此, asInstanceOf只能转换为已擦除类型,即与Scala类型最接近的JVM等效项。 Erased type of String with { type Tag = MyTrait} is String , so it succeeds. String with { type Tag = MyTrait}String擦除类型为String ,因此成功。

The relevant parts of the specification are: 规范的相关部分是:

  1. Standard Library defines asInstanceOf as follows: 标准库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. Type patterns explains how x: String with { type Tag = MyTrait } is matched: 类型模式说明了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. Scala编译器将对这些模式发出“未经检查”的警告,以标记可能丢失类型安全性。

  3. Finally , 最后

    The erasure of a compound type T1 with … with Tn {R} is the erasure of the intersection dominator of T1,…,Tn . T1 with … with Tn {R}擦除T1 with … with Tn {R}的复合类型T1 with … with Tn {R}就是T1,…,Tn的交点控制符的擦除。

    In this case T1 is String , T2 is AnyRef { type Tag = MyTrait } , so you get the intersection dominator of String and AnyRef , which is String . 在这种情况下, T1StringT2AnyRef { type Tag = MyTrait } ,因此您将获得StringAnyRef的交集主导AnyRef ,即String

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

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