我把它写成了一个REPL:
case class Thingy(s: String)
val things = List(Thingy("x"), Thingy("y"))
things.indexOf("x")
返回-1
。但我希望它不会编译,因为"x"
是String
,而不是Thingy
。实际上,事实证明,您将indexOf
放入的类型并不重要:
things.indexOf(42)
things.indexOf(java.time.LocalDate.now())
这些都返回-1。
indexOf
有这个签名:
def indexOf[B >: A](elem: B): Int
我认为>:
表示B
应该是A
的超类型,但这些类都不是我的案例类Thingy
的超类型。
我在这里缺少什么?
答案 0 :(得分:8)
B
被推断为java.io.Serializable
,这是String
和Thingy
的超类型。 1
这是两件事的不幸后果:
Any
,Object
,Serializable
等等。List
是协变的。 2 将indexOf
定义为
def indexOf(elem: A): Int
会将A
置于逆变位置,这是不允许 3 因为它会违反Liskov替换原则:List[Thingy]
是List[Any]
,您可以在.indexOf("x")
上致电List[Any]
,因此您应该可以.indexOf("x")
致电List[Thingy]
。
1 如果他们没有碰巧实施Serializable
,它仍会推断Any
。
2 这是选择不变集合的理由,例如scalaz.IList
。
3 试一试 - 它不会编译:{{1}}