美文网首页Scala
Scala 通俗易懂 ---- 协变、逆变、不变

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

作者: 数星星的鱼 | 来源:发表于2019-11-22 14:21 被阅读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>();      // 错误
    
        }
    

    相关文章

      网友评论

        本文标题:Scala 通俗易懂 ---- 协变、逆变、不变

        本文链接:https://www.haomeiwen.com/subject/wntqwctx.html