编译器能够提供有关类型参数的证据,例如:
def foo[A, B](implicit ev: A <:< B): B
在<:<
中查看Predef
的类型定义
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
$conforms[A]: A <:< A
如何才能说服编译器例如创建<:<[List[String], Seq[String]]
的实例?或<:<[Dog, Animal]
。如果.asInstanceOf
调用引发异常,会发生什么?=>
的子类化?答案 0 :(得分:0)
您可以在scala.Predef
对象中看到它:interp1
@implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] lazy val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
@inline implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
@deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0")
def conforms[A]: A <:< A = $conforms[A]
<:<[-From, +To]
在Form
上是协变的,而在To
上是协变的,因此<:<[Seq[String], Seq[String]]
是<:<[List[String], Seq[String]]
的子类型(因为List[String]
是...的子类型Seq[String]
和-From
是互变的。因此,当您编写implicit ev List[String] <:< Seq[String]
时,编译器将使用<:<[Seq[String], Seq[String]]
当您编写implicit ev T <:< D
并且没有符合A
的{{1}}时,编译器不会编译它,因为没有T <: A <: D
符合{{1 }}。因此,<:<[A, A]
永远不会在运行时在<:<[A, A] <: <:<[T, D]
内部引发异常。
另外,一篇非常好的博客文章:https://github.com/scala-native/scala-native/blob/master/scalalib/overrides-2.11/scala/Predef.scala#L372