加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

<:<运算符如何在Scala中运行?

发布时间:2020-12-16 18:22:51 所属栏目:安全 来源:网络整理
导读:在 Scala中有一个类:见证了类型约束.来自Predef.scala: 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
在 Scala中有一个类<:<见证了类型约束.来自Predef.scala:

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]

它是如何使用的一个例子是TraversableOnce的toMap方法:

def toMap[T,U](implicit ev: A <:< (T,U)): immutable.Map[T,U] =

我不明白的是这是如何工作的.我明白A<:< B在句法上等同于类型<:< [A,B].但是我不知道当且仅当A<:B时,编译器才能找到该类型的隐式.我假设$conforms的定义中的asInstanceOf调用使某种方式成为可能,但是如何?此外,使用抽象类的单例实例而不仅仅是使用对象是否重要?

解决方法

假设我们有以下简单类型层次结构:

trait Foo
trait Bar extends Foo

我们可以要求证明Bar扩展了Foo:

val ev = implicitly[Bar <:< Foo]

如果我们在-Xprint:typer的控制台中运行它,我们将看到以下内容:

private[this] val ev: <:<[Bar,Foo] =
  scala.this.Predef.implicitly[<:<[Bar,Foo]](scala.this.Predef.$conforms[Bar]);

所以编译器选择$conforms [Bar]作为我们要求的隐含值.当然这个值的类型为Bar<:<吧,但因为<:<在其第二个类型参数中是协变的,这是Bar<:<的基本类型. Foo,所以它符合要求. (这里有一些神奇的事实,Scala编译器知道如何找到它正在寻找的类型的子类型,但它是一个相当通用的机制,并且在其行为方面并不太令人惊讶.) 现在假设我们要求证明Bar扩展了String:

val ev = implicitly[Bar <:< String]

如果你打开-Xlog-implicits,你会看到:

<console>:9: $conforms is not a valid implicit value for <:<[Bar,String] because:
hasMatchingSymbol reported error: type mismatch;
 found   : <:<[Bar,Bar]
 required: <:<[Bar,String]
       val ev = implicitly[Bar <:< String]
                          ^
<console>:9: error: Cannot prove that Bar <:< String.
       val ev = implicitly[Bar <:< String]
                          ^

编译器尝试Bar<:<再次禁止,但由于Bar不是String,因此它不是Bar<:<的子类型字符串,所以它不是我们需要的.但$conforms是编译器可以获得的唯一位置<:<实例(除非我们定义了我们自己的,这将是危险的),所以它非常正确地拒绝编译这个废话. 要解决第二个问题:<:< [ - From,To]类是必需的,因为我们需要此类型类的类型参数才有用.单身Any<:<任何值都可以定义为一个对象 - 使用val和匿名类的决定可以说有点简单,但它是一个你不应该担心的实现细节.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读