理解斯卡拉的界限令人困惑

use*_*791 4 generics scala

我正在阅读Demystifying Scala Type System,在第17张幻灯片中有一个片段:

class Test[+A] {
  def test[B >: A](b: B): String = b.toString
}
Run Code Online (Sandbox Code Playgroud)

幻灯片说方法测试将接受A类或任何超类型的A.但似乎我可以通过任何类型进行测试.

vat t = new Test[Int]
t.test("foo")
t.test(List(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)

当我阅读Scala编程时,我也有同样的困惑.

god*_*lka 6

这里要记住的重要一点是,它Any是任何类型的超类型,即

Any >: A
Run Code Online (Sandbox Code Playgroud)

特别是假设

val t = new Test[Int]
Run Code Online (Sandbox Code Playgroud)

这是,AInt.现在我们打电话

t.test("foo")
Run Code Online (Sandbox Code Playgroud)

"foo"是类型String,但字符串是子类型Any,因此可以这样考虑,因此test[B >: A](b : B)可以被b存在"foo"B被调用Any.

下面的例子应该说明这一点,考虑一下

class Test[+A](a : A) {
  def test[B >: A](b : B) : (A,B) = (a,b)
}
Run Code Online (Sandbox Code Playgroud)

现在,使用

val t = new Test(3)
val x = t.test("foo")
Run Code Online (Sandbox Code Playgroud)

我们得到

x: (Int, Any) = (3,foo)
Run Code Online (Sandbox Code Playgroud)

最后,为了添加一些细节,Scala并不总是选择Any,而是最不常见的超类型AB.这恰好是Any针对IntString(参见http://www.scala-lang.org/old/node/128),但可能与其他示例有所不同,例如,

val s = new Test(Nil)
val y = s.test("foo")
val z = s.test(List(1))
Run Code Online (Sandbox Code Playgroud)

我们将得到

y: (scala.collection.immutable.Nil.type, java.io.Serializable) = (List(),foo)
z: (scala.collection.immutable.Nil.type, List[Int]) = (List(),List(1))
Run Code Online (Sandbox Code Playgroud)

另请注意,下限不会阻止传递子类型 A

scala> val a = new Test(new AnyRef())
a: Test[java.lang.Object] = Test@6771a12

scala> a.test("foo")
res6: (java.lang.Object, java.lang.Object) = (java.lang.Object@78b99f12,foo)
Run Code Online (Sandbox Code Playgroud)

所以,问题是,什么是低级类型边界有用?一个可能的答案是它们可以用于"控制""输出"位置的类型,通常用于协变类型参数,参见,例如,http://docs.scala-lang.org/tutorials/tour/lower -type-bounds.html粗略地说,当将一个元素附加到(协变)类型列表时A,您需要确保结果列表是"至少"类型A.(我很抱歉这部分内容很浪漫,但是因为它超出了原始问题的范围,我只是想简要介绍一下为什么需要它们,为了得到完整答案,最好创建它一个新问题)