Scala 差异
差异是指子类型关系的相互联系,这些子类型要么是复杂的类型,要么是它们的组成类型。差异解释了有参数的类型的继承关系。这些类型属于通用类,它把一个类型当作一个参数。在有Variance的情况下,人们可以在复杂类型之间建立关系,如果没有Variance,我们就无法重申抽象类。Scala变量有三种类型,具体如下。
- 共变(Covariant )
- 同变数
- 不变型
一些重要的观点。
- 在Scala中,集合的类型可以通过变体(Variances)更安全地构建。
- 变体可以为我们提供一些额外的可调整的进展。
- 它也有助于开发真实的应用程序。
- 变体可以应用于任何Scala类型,如List、Sets等。
变体的类型
让我们来详细讨论每一种类型。
- 协变量。如果一个泛型类有一个类型参数T,那么它的协变符号将是[+T]。假设我们有两个Scala的List类型,即S和T,其中,S是T的子类型,那么你可以说List[S]也是List[T]的子类型。如果两个类型有这样的关系,那么它们就属于共变类型。List[T]可以被称为通用类型。
语法:
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是协变的。
* 特质应用在这里被用来快速地将对象变成可操作的程序。
- 同变性。如果一个泛型类有一个类型参数T,那么它的共变符号将是[-T]。假设我们有两个Scala的List类型,即S和T,其中,S是T的子类型,但List[T]是List[S]的子类型。如果两个类型有这样的关系,那么它们就属于Contravariant类型。它与协变量相反。
语法:
List[-T]
在这里,T是类型参数,-是Contravariance的符号。
示例:
// 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
它是Contravariant,所以,我们能够用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]”等类是可变的,所以它们有不变的类型参数,如果我们在继承关系或子类型中使用不变的类型参数,我们会得到一个编译错误。