Scala类型边界 - 没有抛出错误?

时间:2014-07-14 18:37:32

标签: scala

我目前正试图围绕scala类型边界。据我所知,他们习惯于根据类型来限制泛型中可以使用的类型。等级关系。

在我看来,以下代码不能正常工作; testdef采用两个既不是子类也不是超类的参数,并且绑定的B< A应该抛出一个错误。但这并没有发生;这段代码运行得很好。

case class testclass1(val1: Int)
case class testclass2(val2: Int)

def testdef1[A, B <: A](a: A, b: B): (A, B) = {
  (a, b)
}

testdef1(testclass1(1), testclass2(2))

但是,以下内容会引发错误,因为testdef2只接受testclass1或testclass1的任何子类型(testclass2 isn&#39; t):

def testdef2[A <: testclass1](a: A): A = {
  a
}
testdef2(testclass2(1))

那么,为什么第一个例子没有强制执行泛型A和B(testclass1和testclass2)之间的关系?

1 个答案:

答案 0 :(得分:2)

使用像testdef1这样的通用方法,编译器将推断仍然允许它进行类型检查的类型参数的最具体类型。将A设置为testclass1并将B设置为testclass2会为他们提供使用传入参数的最具体类型,但它不会进行类型检查,因为{{违反了1}}。然后,编译器会对类型参数进行泛化,并发现将B <: A设置为A就足以让它进入类型检查。基本上它决定:

Product with Serializable

意思是:

testdef1(testclass1(1), testclass2(2))

现在,testdef1[Product with Serializable, testclass2](testclass1(1), testclass2(2)) Product来自哪里?所有案例类都自动成为这些特征的子类型,并提供适当的方法定义。因为Serializabletestclass1都是案例类,testclass2是两种类型中最具体的类型,技术上称为最小上限,或者&#34; lub&#34; 。它类似于整数的最小公倍数。

事实上,因为编译器可以决定Product with SerializableA,所以Any无论传递给它都会进行类型检查。

(感谢Daenyth指出testdef1变为A。)