结构类型没有调用正确的实现?

时间:2016-02-16 15:37:33

标签: scala reflection structural-typing

我的印象是Structural Types在引擎盖下使用反射(表示需要tell the compiler来启用"-language:reflectiveCalls")并且无论哪种对象与该类型相匹配都将使用它自己的该功能的版本。例如,如果我在.contains上致电Seq而不是使用Seq版本,如果我在String上调用它,那么它将使用SeqLike中定义的版本{3}}它来自Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_79). Type in expressions to have them evaluated. Type :help for more information. scala> type Containable = { def contains(elem:Any):Boolean } defined type alias Containable scala> val myMap: Map[String, Containable] = Map("A" -> "B", "C" -> Seq("A","B")) myMap: Map[String,Containable] = Map(A -> B, C -> List(A, B)) scala> myMap("A").contains("B") res0: Boolean = false scala> myMap("C").contains("B") res1: Boolean = true scala> "B".contains("B") res3: Boolean = true

所以在scala 2.10.3中,为什么会发生这种情况:

String

正如您所看到的,String。contains(Containable)为自身返回true,但如果在被解释为==类型时被调用则不会,即使它与StringOps类中定义的方法。

我感觉这与.contains的实施有关,因为isInstanceOf文档说:

  

如果此序列的元素相等(由==确定)为elem,则为true,否则为false。

通过scala> val aVal = myMap("A") aVal: Containable = B scala> aVal.isInstanceOf[String] res5: Boolean = false scala> aVal.isInstanceOf[Seq[_]] res6: Boolean = true

检查类型的结果使这种感觉更加复杂
-J-XX:+CMSClassUnloadingEnabled
-J-Xmx2G

在回应有关编译器错误的评论时,这里是StringOps

1 个答案:

答案 0 :(得分:3)

当您将String插入Map时,它们会被转换为WrappedString,因为String没有带有签名的方法在Containable中定义。

scala> implicitly[String => Containable]
res10: String => Containable = <function1>

scala> res10("s")
res11: Containable = s

scala> res11.getClass
res12: Class[_ <: AnyRef] = class scala.collection.immutable.WrappedString

在Scala 2.10.x WrappedString中有一个方法contains(elem: Any): Boolean。它检查elem是否是调用contains的集合的元素。 WrappedString表示Char s的集合,因此如果您给它String,该方法将永远不会返回true。 在scala 2.11.x中,contains方法已被更改,因此它只接受Char s。

String本身有一个方法contains(elem: java.lang.CharSequence): BooleanStringCharSequence,因此当您在contains("B")上调用String时,将调用该方法,String将不会转换为WrappedString }}