Scala

Scala 通俗易懂 ---- 协变、逆变、不变

2019-11-22  本文已影响0人  数星星的鱼

协变、逆变、不变

Scala 语言中协变、逆变、不变是指拥有泛型的类型,在声明和赋值时的对应关系

协变:声明时泛型是父类,赋值时泛型可以是父类也可以是子类

逆变:声明时泛型是子类,赋值时泛型可以是子类也可以是父类

不变:声明时泛型是什么类型,赋值时也只能是什么类型

示例说明

准备工作

现有类声明如下:

// Dog 类继承自 Animal 类
class Animal
class Dog extends Animal

协变

声明语法:

// 协变类型,泛型前面有一个'加号'
class MyList1[+V]

示例代码:

val list1_1: MyList1[Animal] = new MyList1[Dog]()       // 正确
val list1_2: MyList1[Animal] = new MyList1[Animal]()    // 正确
val list1_3: MyList1[Dog] = new MyList1[Animal]()       // 出错

说明:

协变类型声明时泛型是父类,赋值时泛型可以是父类,也可以是子类

逆变

声明语法:

// 逆变类型,泛型前面有一个'减号'
class MyList2[-V]

示例代码:

val list2_2: MyList2[Dog] = new MyList2[Dog]()          // 正确
val list2_3: MyList2[Dog] = new MyList2[Animal]()       // 正确
val list2_1: MyList2[Animal] = new MyList2[Dog]()       // 出错

说明:

逆变类型声明时泛型是子类,赋值时泛型可以是子类,也可以是父类

不变

声明语法:

// 不变类型,泛型前面'没有符号'
class MyList3[V]

示例代码:

val list3_2: MyList3[Dog] = new MyList3[Dog]()          // 正确
val list3_3: MyList3[Dog] = new MyList3[Animal]()       // 出错
val list3_1: MyList3[Animal] = new MyList3[Dog]()       // 出错

说明:

不变类型声明时泛型是子类,赋值时泛型只能是子类

完整代码

    // Dog 类继承自 Animal 类
    class Animal
    class Dog extends Animal

    // 声明拥有泛型的类,泛型前面有一个'加号'
    class MyList1[+V]

    // 声明拥有泛型的类,泛型前面有一个'减号'
    class MyList2[-V]

    // 声明拥有泛型的类,泛型前面'没有符号'
    class MyList3[V]

    def main(args: Array[String]): Unit = {

        // 协变类型声明时泛型是父类,赋值时泛型可以是父类,也可以是子类
        val list1_1: MyList1[Animal] = new MyList1[Dog]()       // 正确
        val list1_2: MyList1[Animal] = new MyList1[Animal]()    // 正确
        val list1_3: MyList1[Dog] = new MyList1[Animal]()       // 出错

        // 逆变类型声明时泛型是子类,赋值时泛型可以是子类,也可以是父类
        val list2_2: MyList2[Dog] = new MyList2[Dog]()          // 正确
        val list2_3: MyList2[Dog] = new MyList2[Animal]()       // 正确
        val list2_1: MyList2[Animal] = new MyList2[Dog]()       // 出错

        // 不变类型声明时泛型是子类,赋值时泛型只能是子类
        val list3_2: MyList3[Dog] = new MyList3[Dog]()          // 正确
        val list3_1: MyList3[Animal] = new MyList3[Dog]()       // 出错
        val list3_3: MyList3[Dog] = new MyList3[Animal]()       // 出错
    }

对比Java

Java 中只有不变,没有协变也没有不变,声明时泛型是什么类型,赋值时泛型也必须是什么类型

示例代码如下:

    class Animal {}

    class Dog extends Animal {}

    static class MyList<X extends Animal> {}

    public static void main(String[] args) {
        MyList<Animal> m1 = new MyList<Animal>();   // 正确
        MyList<Dog> m2 = new MyList<Dog>();         // 正确
        MyList<Animal> m3 = new MyList<Dog>();      // 错误
        MyList<Dog> m4 = new MyList<Animal>();      // 错误

    }
上一篇下一篇

猜你喜欢

热点阅读