斯卡拉 |差异
方差是子类型关系的互连,这些关系既可以是复杂类型,也可以是其组成类型。方差解释了其中具有参数或参数的类型的继承相关性。这些类型属于泛型类,它采用类似于参数的类型。在存在 Variance 的情况下,可以创建复杂类型之间的关系,而在没有 Variance 的情况下,我们将无法重复抽象类。 Scala Variances 有以下三种类型:
- 协变
- 逆变的
- 不变的
一些重要的点:
- 在 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] 等类是可变的,所以它们都有不变的类型参数,如果我们在继承关系或子类型中使用不变的类型参数,那么我们将得到一个编译错误。