目录
1 协变和逆变
Scala中的协变和逆变是解决类型转换问题的机制,它们与Scala的泛型类型参数有关。在Scala中,协变和逆变可以通过在类型参数前面添加"+"和"-"符号来实现。
协变表示类型参数能够被隐式地转换为更具体的类型,例如,如果B是A的子类型,则List[B]是List[A]的子类型。这可以通过在类型参数前面添加"+"符号来实现,例如:
class Animal
class Cat extends Animal
class Container[+A](val elem: A)
val catContainer: Container[Cat] = new Container[Cat](new Cat)
val animalContainer: Container[Animal] = catContainer // 协变
这里,Container[Cat]是Container[Animal]的子类型,因为Cat是Animal的子类型。因此,我们可以将catContainer赋值给animalContainer。
相反,逆变表示类型参数能够被隐式地转换为更一般的类型,例如,如果B是A的子类型,则Comparator[A]是Comparator[B]的子类型。这可以通过在类型参数前面添加"-"符号来实现,例如:
class Animal
class Cat extends Animal
class Comparator[-A] {
def compare(a1: A, a2: A): Int = ???
}
val catComparator: Comparator[Cat] = new Comparator[Animal]
这里,Comparator[Animal]是Comparator[Cat]的子类型,因为Animal是Cat的父类型。因此,我们可以将catComparator赋值给animalComparator。
2 泛型上下限
Scala的泛型类型参数还支持上下限限定,它们可以用来限制类型参数的范围。上限类型限定表示类型参数必须是某个类型的子类型,下限类型限定表示类型参数必须是某个类型的父类型。
例如,我们可以定义一个接受某个类型的List并返回该类型的最大值的方法,该类型必须是Comparable类型的子类型:
def max[T <: Comparable[T]](a: T, b: T): T = {
if (a.compareTo(b) < 0) b else a
}
val maxInt = max(3, 5) // 5
val maxString = max("hello", "world") // world
这里,"<: Comparable[T]"表示类型参数T必须是Comparable[T]的子类型,因此我们可以调用max方法并传递Int和String类型的参数。
3 上下文限定
上下文限定是另一种类型约束,它使用implicit关键字和隐式参数来实现。上下文限定通常用于需要某个类型的隐式值的方法或类中。
例如,我们可以定义一个需要一个类型为Ordering[T]的隐式值的方法,该方法接受两个类型为T的参数并返回较小的那个:
def min[T](a: T, b: T)(implicit ord: Ordering[T]): T = {
if (ord.compare(a, b) < 0) a else b
}
val minInt = min