📜  Scala – 反方差

📅  最后修改于: 2022-05-13 01:55:48.947000             🧑  作者: Mango

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],但不允许取反。