Scala – 反方差
反方差与协方差正好相反。反方差在类和类型参数之间创建了类似的子类型关系。因此,逆变表明如果存在两个参数化类型,使得 S 是 T 的子类型,则 List[T] 是 List[S] 的子类型。我们可以使用符号 [-S] 使泛型类逆变。只要类型(通用)参数“使用”类型 S 或接受的类型,我们就可以使用逆变。我们也可以使用逆变器作为方法参数类型,但不能作为方法返回类型,因为它会产生编译错误。
句法:
List[-T]
这里,T 是类型参数,- 是逆变的符号。
示例 1:让我们考虑一个示例,其中 Printer[S] 是一个打印某种类型 S 的类。我们将在这里定义一个类型的子类:
// Scala program to illustrate contra-variance
abstract class Printer[-S]
{
// Here -S denotes Contra-Variant
// type S
def print(value: S): Unit
}
abstract class Flower
{
def name: String
}
// Create subclass of Flower
case class Lily(name: String) extends Flower
class FlowerPrinter extends Printer[Flower]
{
def print(flower: Flower): Unit =
// Display name of flower
println("The flower's name is: " + flower.name)
}
class LilyPrinter extends Printer[Lily]
{
def print(lily: Lily): Unit =
println("Lily's name is: " + lily.name)
}
// Inherit the main method
object Contravariance extends App
{
// Assign value
val lily : Lily = Lily("White Lily")
// Define method to print the name
def printMyLily(printer: Printer[Lily]): Unit =
{
printer.print(lily)
}
// Create objects
val lilyPrinter: Printer[Lily] = new LilyPrinter
val flowerPrinter: Printer[Flower] = new FlowerPrinter
printMyLily(lilyPrinter)
printMyLily(flowerPrinter)
}
输出:
Lily's name is: White Lily
The flower's name is: White Lily
解释:在这段代码中,如果 Printer[Lily] 可以打印任何 Lily,Printer[Flower] 可以打印 Flower,那么 Printer[Flower] 也可以打印 Lily。但是反过来不能,因为 Printer[Lily] 不知道如何打印任何 Flower。因此,我们可以使用 Print[Flower] 作为 Printer[Lily] 的替代品,我们可以通过使 Printer[S] Contra-Variant 来实现。
示例 2:考虑这个示例通用类车辆:
// Scala program to illustrate contra-variance
abstract class GetVehicleName[-S]
{
// Here -S denotes Contra-Variant
// type S
def print(value: S): Unit
}
abstract class Vehicle
{
def name: String
}
// Create subclass of Flower
case class Bike(name: String) extends Vehicle
class VehicleName extends GetVehicleName[Vehicle]
{
def print(vehicle: Vehicle): Unit =
println("The vehicle's name is: " + vehicle.name)
}
class BikeName extends GetVehicleName[Bike]
{
def print(bike: Bike): Unit =
println("Bike's name is: " + bike.name)
}
// Inherit the main method
object Contravariance extends App
{
// Assign value
val bike : Bike = Bike("Yamaha Fazer")
// Define method to print the name
def printMyBike(getVehicleName: GetVehicleName[Bike]): Unit =
{
getVehicleName.print(bike)
}
// Create objects
val bikeName: GetVehicleName[Bike] = new BikeName
val vehicleName: GetVehicleName[Vehicle] = new VehicleName
printMyBike(bikeName)
printMyBike(vehicleName)
}
输出 :
Bike's name is: Yamaha Fazer
The vehicle's name is: Yamaha Fazer
解释:在这个例子中,由于逆变,我们得到了相同的输出。由于抽象类 Get_vehicle_name 是反变的,我们可以将 Get_vehicle_name[Vehicle] 替换为 Get_vehicle_name[Bike],但不允许取反。