spark笔记之Scala中的协变、逆变、非变

1.1. 协变、逆变、非变介绍ide

协变和逆变主要是用来解决参数化类型的泛化问题。Scala的协变与逆变是很是有特点的,彻底解决了Java中泛型的一大缺憾;举例来讲,Java中,若是有 A是 B的子类,但 Card[A] 却不是 Card[B] 的子类;而 Scala 中,只要灵活使用协变与逆变,就能够解决此类 Java 泛型问题;scala

因为参数化类型的参数(参数类型)是可变的,当两个参数化类型的参数是继承关系(可泛化),那被参数化的类型是否也能够泛化呢?Java中这种状况下是不可泛化的,然而Scala提供了三个选择,即协变(“+”)、逆变(“-”)和非变。code

下面说一下三种状况的含义,首先假设有参数化特征Queue,那它能够有以下三种定义。继承

(1)  trait Queue[T] {}it

这是非变状况。这种状况下,当类型B是类型A的子类型,则Queue[B]与Queue[A]没有任何从属关系,这种状况是和Java同样的。ast

(2) trait Queue[+T] {} 
        这是协变状况。这种状况下,当类型B是类型A的子类型,则Queue[B]也能够认为是Queue[A]的子类型,即Queue[B]能够泛化为Queue[A]。也就是被参数化类型的泛化方向与参数类型的方向是一致的,因此称为协变。class

(3)   trait Queue[-T] {}泛型

这是逆变状况。这种状况下,当类型B是类型A的子类型,则Queue[A]反过来能够认为是Queue[B]的子类型。也就是被参数化类型的泛化方向与参数类型的方向是相反的,因此称为逆变。object

1.2. 协变、逆变、非变总结总结

Ø C[+T]:若是A是B的子类,那么C[A]是C[B]的子类。

Ø C[-T]:若是A是B的子类,那么C[B]是C[A]的子类。

Ø C[T]: 不管A和B是什么关系,C[A]和C[B]没有从属关系。

1.3. 案例

package cn.itcast.scala.enhance.covariance

 

class Super

class Sub extends Super

//协变

class Temp1[+A](title: String)

//逆变

class Temp2[-A](title: String)

//非变

class Temp3[A](title: String)

 

object Covariance_demo{

  def main(args: Array[String]) {

    //支持协变 Temp1[Sub]仍是Temp1[Super]的子类

    val t1: Temp1[Super] = new Temp1[Sub]("hello scala!!!")

    //支持逆变 Temp1[Super]是Temp1[Sub]的子类

    val t2: Temp2[Sub] = new Temp2[Super]("hello scala!!!")

    //支持非变 Temp3[Super]与Temp3[Sub]没有从属关系,以下代码会报错

    //val t3: Temp3[Sub] = new Temp3[Super]("hello scala!!!")

 

//val t4: Temp3[Super] = new Temp3[Sub]("hello scala!!!")

    println(t1.toString)

    println(t2.toString)

  }

}
相关文章
相关标签/搜索