我目前正试图围绕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)之间的关系?
答案 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
来自哪里?所有案例类都自动成为这些特征的子类型,并提供适当的方法定义。因为Serializable
和testclass1
都是案例类,testclass2
是两种类型中最具体的类型,技术上称为最小上限,或者&#34; lub&#34; 。它类似于整数的最小公倍数。
事实上,因为编译器可以决定Product with Serializable
是A
,所以Any
无论传递给它都会进行类型检查。
(感谢Daenyth指出testdef1
变为A
。)