📜  斯卡拉 |差异

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

斯卡拉 |差异

方差是子类型关系的互连,这些关系既可以是复杂类型,也可以是其组成类型。方差解释了其中具有参数参数的类型的继承相关性。这些类型属于泛型类,它采用类似于参数的类型。在存在 Variance 的情况下,可以创建复杂类型之间的关系,而在没有 Variance 的情况下,我们将无法重复抽象类。 Scala Variances 有以下三种类型:

  1. 协变
  2. 逆变的
  3. 不变的

一些重要的点:

  • 在 Scala 中,集合的类型可以通过 Variance 更安全地构建。
  • 差异可以为我们提供一些额外的可调整的进步。
  • 它还有助于开发真实的应用程序。
  • 方差可以应用于任何 Scala 类型,如 List、Sets 等。
差异类型

让我们详细讨论每种类型。

  • 协变:如果泛型类有类型参数 T,那么它的协变表示法将是 [+T]。假设我们有两种 Scala 的 List 类型,即 S 和 T。其中,S 是 T 的子类型,那么您可以说 List[S] 也是 List[T] 的子类型。如果两种类型像这样相关,那么它们属于协变类型。 List[T] 可以称为Generic
    句法:
    List[+T]

    这里, T是类型参数, +是协方差的符号。
    例子:

    // Scala program of covariant
    // type
      
    // Creating an abstract class
    // for Student
    abstract class Student
    {
        def name: String
    }
      
    // Creating a sub-class Girls
    // of Student
    case class Girls(name: String) extends Student
      
    // Creating a sub-class Boys
    // of Student
    case class Boys(name: String) extends Student
      
    // Creating an Object Covariance
    // that inherits main method of
    // App
    object Covariance extends App
    {
        // Creating a method
        def Studentnames(students: List[Student]): Unit =
        {
            students.foreach { student =>
          
            // Displays students name
            println(student.name)
        }
        }
      
        // Assigning names 
        val boys: List[Boys] = List(Boys("Kanchan"), Boys("Rahul"))
        val girls: List[Girls] = List(Girls("Nidhi"), Girls("Geeta"))
      
        // Accessing list of boys
        Studentnames(boys)
      
        // Accessing list of girls
        Studentnames(girls)
    }
    
    输出:
    Kanchan
    Rahul
    Nidhi
    Geeta
    

    在这里,男生和女生的列表都属于学生列表,因为他们是它的子类型,所以在这里调用超类型学生时会显示所有学生的名字。
    笔记:

    • 这里使用抽象类来应用协变,因为它具有 List[+T] ,其中类型参数 T 是协变的。
    • 这里使用了一个 trait App来快速将对象转换为可操作的程序。

  • 逆变:如果泛型类有类型参数 T,那么它的逆变表示法将是 [-T]。假设我们有两种 Scala 的 List 类型,即 S 和 T。其中,S 是 T 的子类型,而 List[T] 是 List[S] 的子类型。如果两种类型像这样相关,那么它们属于逆变类型。它与协变相反。
    句法:
    List[-T]

    这里, T是类型参数, -是逆变的符号。
    例子:

    // Scala program of Variance of
    // Contravariant type
      
    // abstract class with a contravariant 
    // type parameter
    abstract class Show[-T] 
    {
      
        // Method for printing
        // type T
        def print(value: T): Unit
    }
      
    // A class structure
    abstract class Vehicle
    {
        def name: String
    }
      
    // Creating sub-class of Vehicle
    case class Car(name: String) extends Vehicle
      
    // Creating sub-class of class
    // Show
    class VehicleShow extends Show[Vehicle] 
    {
        def print(vehicle: Vehicle): Unit =
      
        // Displays name of the vehicle
        println("The name of the vehicle is: " + vehicle.name)
    }
      
    // Creating sub-class of class
    // Show
    class CarShow extends Show[Car] 
    {
        def print(car: Car): Unit =
      
        // Displays name of the car
        println("The name of the car is: " + car.name)
    }
      
    // Inheriting main method of 
    // the trait App
    object Contravariance extends App 
    {
      
        // Assigning value to the name 
        val newCar: Car = Car("Scorpio")
      
        // Defining a method that
        // prints the name
        def printnewCar(show: Show[Car]): Unit = 
        {
            show.print(newCar)
        }
      
        // Creating objects
        val showcar: Show[Car] = new CarShow
        val showvehicle: Show[Vehicle] = new VehicleShow
      
        // Accessing name
        printnewCar(showcar)
        printnewCar(showvehicle)
    }
    
    输出:
    The name of the car is: Scorpio
    The name of the vehicle is: Scorpio
    

    它是逆变的,所以我们可以用 Show[Vehicle] 代替 Show[Car],这就是为什么 vehicle 和 car 返回相同的名称。

  • 不变:在 Scala 中,泛型类型默认是不变的。假设我们有两种 Scala 的 List 类型,即 S 和 T。其中,S 是 T 的子类型,但 List[T] 和 List[S] 根本不相关,那么它们属于不变类型。
    句法:
    List[T]

    在这里,我们不使用任何符号来表示不变关系。
    注意: Array[T], ListBuffer[T], ArrayBuffer[T] 等类是可变的,所以它们都有不变的类型参数,如果我们在继承关系或子类型中使用不变的类型参数,那么我们将得到一个编译错误。