我的印象是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
答案 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): Boolean
。 String
是CharSequence
,因此当您在contains("B")
上调用String
时,将调用该方法,String
将不会转换为WrappedString
}}