为什么类型参数边界 T <: Comparable[T] 在 T = Int 时失败?
问题的原因是类型参数边界T <: Comparable[T]在T = Int的情况下失败。这是因为Int类型不是Comparable[Int]的子类型。解决方法是使用视图界定(view bound),即将类型参数边界改为T <% Comparable[T]。这样,编译器会在需要时自动进行类型转换,将Int转换为Comparable[Int]。
下面是一个示例代码:
class Foo[T <% Comparable[T]](val x: T) val foo = new Foo(3)
在这个示例中,我们定义了一个泛型类Foo,它接受一个类型参数T,并要求T能够隐式转换为Comparable[T]。然后我们创建了一个Foo实例,传入一个Int类型的参数3。
通过使用视图界定,编译器会在需要时自动调用Predef.intWrapper将Int类型转换为Comparable[Int]类型。这样,我们就可以成功地创建一个Foo[Int]的实例。
- 类型参数边界T <: Comparable[T]要求T必须是Comparable[T]的子类型。
- 当T = Int时,Int并不是Comparable[Int]的子类型,因此类型参数边界失败。
- 使用视图界定T <% Comparable[T]可以让编译器自动进行类型转换,将Int转换为Comparable[Int],从而满足类型参数边界的要求。
问题的出现原因是在使用类型参数边界时,给定的参数类型Int不满足T <: Comparable[T]的约束条件,因为Int类型不是Comparable[Int]的子类型。
解决方法是使用上下文界定(context bound)。上下文界定使用了Ordering[T]或java.util.Comparator[T]的隐式参数来表示在构造函数调用时有一个隐式的Ordering[T]或java.util.Comparator[T]存在。这等效于添加一个隐式参数。
采用这种方式的优点是可以根据上下文使用一个备选的排序方式。
通过在范围内定义一个对象,可以实现使用不同的排序方式:
// 默认情况下,new Foo("a", "c", "b").items == List("a", "b", "c")
class Foo[T: Ordering](xs: T*) {
val items = xs.toList.sorted
}
// 在作用域内定义此对象后,
// new Foo("a", "c", "b").items == List("c", "b", "a")
implicit val descending = Ordering[String].reverse
我之前对上下文界定并不了解,阅读了您的回答后我去查阅了更多资料。非常有用和信息丰富。谢谢。