Scala indexOf接受一切

jqn*_*qno 6 scala

我把它写成了一个REPL:

case class Thingy(s: String)
val things = List(Thingy("x"), Thingy("y"))
things.indexOf("x")
Run Code Online (Sandbox Code Playgroud)

那回来了-1.但我本来以为它不会编译,因为它"x"是a String,而不是a Thingy.事实上,事实证明你投入的类型并不重要indexOf:

things.indexOf(42)
things.indexOf(java.time.LocalDate.now())
Run Code Online (Sandbox Code Playgroud)

这些都返回-1.

indexOf 有这个签名:

def indexOf[B >: A](elem: B): Int
Run Code Online (Sandbox Code Playgroud)

我认为>:手段B应该是超类型A,但这些类都不是我的案例类的超类型Thingy.

我在这里错过了什么?

Chr*_*tin 8

B被推断为java.io.Serializable,它是两者的超类型StringThingy.1

这是两件事的不幸后果:

  1. Scala的多余父类型的所有/最值股(Any,Object,Serializable等).
  2. List是协变的.2

定义indexOf

def indexOf(elem: A): Int
Run Code Online (Sandbox Code Playgroud)

会把A在逆变位置,这是不允许的3,因为这将违反里氏替换原则:一个List[Thingy]List[Any],你可以叫.indexOf("x")List[Any],因此,你应该能够调用.indexOf("x")List[Thingy].


1如果他们两个都没有实施Serializable,它仍然会推断Any.

2这是选择不变集合的理由,例如scalaz.IList.

3试一试 - 它不会编译:trait Foo[+A] { def bar(a: A) }