Scala 通俗易懂 ---- 協(xié)變、逆變、不變

協(xié)變、逆變、不變

Scala 語言中協(xié)變、逆變、不變是指擁有泛型的類型,在聲明和賦值時的對應(yīng)關(guān)系

協(xié)變:聲明時泛型是父類,賦值時泛型可以是父類也可以是子類

逆變:聲明時泛型是子類,賦值時泛型可以是子類也可以是父類

不變:聲明時泛型是什么類型,賦值時也只能是什么類型

示例說明

準(zhǔn)備工作

現(xiàn)有類聲明如下:

// Dog 類繼承自 Animal 類
class Animal
class Dog extends Animal

協(xié)變

聲明語法:

// 協(xié)變類型,泛型前面有一個'加號'
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]()       // 出錯

說明:

協(xié)變類型聲明時泛型是父類,賦值時泛型可以是父類,也可以是子類

逆變

聲明語法:

// 逆變類型,泛型前面有一個'減號'
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 = {

        // 協(xié)變類型聲明時泛型是父類,賦值時泛型可以是父類,也可以是子類
        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 中只有不變,沒有協(xié)變也沒有不變,聲明時泛型是什么類型,賦值時泛型也必須是什么類型

示例代碼如下:

    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>();      // 錯誤

    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容