協(xié)變逆變的概念
可變性是以一種類型安全的方式道宅,將一個對象當(dāng)做另一個對象來使用萧豆。如果不能將一個類型替換成為另一個類型臼朗,那么這個類型就稱之為:不變量。
協(xié)變:如果某個返回的類型可以由其派生類替換蝎土,那么這個類型就是支持協(xié)變的视哑。
逆變:如果某個參數(shù)類型可以由其基類替換,那么這個類就是支持逆變的誊涯。
如Function, 在這里R?作為函數(shù)的返回值, 所以這個泛型要協(xié)變, 而T用在函數(shù)的參數(shù)上所以要用逆變挡毅。
Function<? super Dog,? extends Animal> f1;
協(xié)變
如:List<Number>和List<Integer>之間是沒有繼承關(guān)系的。
但是直觀上會覺得,Integer是Number的子類, 所以List<Integer>應(yīng)是List<Number>的子類暴构。
如果想要這種效果, 就要用協(xié)變跪呈。
List<? extends Number>這樣List<Integer>就能成為List 子類, 也就是可以賦值。
List<Integer>b = new ArrayList<>();
List<? extends Number> a = b;?
逆變
假設(shè)有以下繼承關(guān)系:
車 > 轎車 > 標(biāo)準(zhǔn)轎車 > 高級轎車
現(xiàn)在有一個人聲稱自己能修理所有的標(biāo)準(zhǔn)轎車, 所以發(fā)出了以下公告:
修理(List<標(biāo)準(zhǔn)轎車> cars)
假設(shè)我現(xiàn)在有List<轎車>和 List<高級轎車>
那么這個人到底能修理哪個呢? 從上面的函數(shù)聲明來看都不可以.
再來看看這個人的聲明
他說能夠修理所有標(biāo)準(zhǔn)轎車
那么因為標(biāo)準(zhǔn)轎車擴(kuò)展了轎車, 所以如果能夠修理標(biāo)準(zhǔn)轎車, 那么應(yīng)當(dāng)可以修理轎車
所以這個函數(shù)應(yīng)當(dāng)可以接受所有標(biāo)準(zhǔn)轎車的父類
也就是說 List<轎車> 能夠傳入 以List<標(biāo)準(zhǔn)轎車>為參數(shù)的函數(shù)
換句話說 List<轎車> 是List<標(biāo)準(zhǔn)轎車>的子類, 這樣才能傳入?yún)?shù)
所以上面的公告要用逆變, 改成如下:
修理(List<? super 標(biāo)準(zhǔn)轎車> cars)
設(shè)計模式
里氏替換原則:的內(nèi)容可以描述為: “派生類(子類)對象可以在程式中代替其基類(超類)對象取逾『穆蹋”
墨子的智慧
《墨子:小取》中說,“白馬砾隅,馬也误阻;乘白馬,乘馬也。驪馬究反,馬也寻定;乘驪馬,乘馬也”精耐。文中的驪馬是黑的馬狼速。意思就是白馬和黑馬都是馬,乘白馬或者乘黑馬就是乘馬卦停。在面向?qū)ο笾形覀兛梢赃@樣理解向胡,馬是一個父類,白馬和黑馬都是馬的子類沫浆,我們說乘馬是沒有問題的捷枯,那么我們把父類換成具體的子類,也就是乘白馬和乘黑馬也是沒有問題的专执,這就是我們上邊說的里氏替換原則淮捆。
墨子同時還指出了反過來是不能成立的”竟桑《墨子:小取》中說:“娣攀痊,美人也,愛娣拄显,非愛美人也”苟径。娣是指妹妹,也就是說我的妹妹是沒人躬审,我愛我的妹妹(出于兄妹感情)棘街,但是不等于我愛美人。在面向?qū)ο罄锞褪浅斜撸廊耸且粋€父類遭殉,妹妹是美人的一個子類。哥哥作為一個類有“喜愛()”方法博助,可以接受妹妹作為參量险污。那么這個“喜愛()”不能接受美人類的實例,這也就說明了反過來是不能成立的富岳。