多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > Scala之“逆變”合理性的思考

Scala之“逆變”合理性的思考

來源:程序員人生   發布時間:2016-11-20 17:05:07 閱讀次數:2440次

Scala之“逆變”公道性的思考

對逆變的概念可以參考本系列的前1篇文章: Scala之類型參數化:Type Parameterization 本文的重點是要解釋“逆變”的公道性。本文原文出處: http://blog.csdn.net/bluishglc/article/details/52585991 嚴禁任何情勢的轉載,否則將拜托CSDN官方保護權益!

在思考“逆變”的公道性這個問題上,我們需要清晰地認識到1個條件,即父類與子類之間的關系實質,我們說:如果類A是類B的父類,那末所有出現類A聲明的地方,我們都可使用類B的實例進行替換,或說所有適用于類A的操作一樣適用于類B,簡言之就是子類型可以透明無害地替換父類型(也就是里氏替換原則),由于子類型1定也是父類型,但父類型未必1定是子類型(有其他子類型),上述原則就是大家所熟知的里氏替換原則。

Liskov Substitution Principle (里氏替換原則)

It is safe to assume that a type T is a subtype of a type U if you can substitute a value of type T wherever a value of type U is required. 

The principle holds if T supports the same operations as U and all of T’s operations require less and provide more than the corresponding operations in U.

在回顧完上述表述以后,我們來重新審視1下“逆變”存在的公道性。首先定義以下1個Animal類族:

scala> class Animal defined class Animal scala> class Bird extends Animal defined class Bird scala> class Dog extends Animal defined class Dog

現在有f1,f2兩個函數:

def f1(x: Bird): Unit // instance of Function1[Bird, Unit] def f2(x: Animal): Unit // instance of Function1[Animal, Unit]

在這里,f1是f2的父類。為何?我們知道,Function1的類型聲明是Function1[-T1,+R],即函數是雖參數類型逆變,返回值類型協變的。其中隨返回值類型協變是很容易理解的,隨參數類型逆變常常讓人費解,對此,我們一樣使用前面提到的原則進行判定:父類可以被子類替換,反之則不可以,但是這里的情況會略微有些復雜,由于我們要判斷的是函數類型之間的可替換關系(即父子關系),我們可以認為函數是1種“復合”類型,它們的類型是由它們的參數和返回值的類型決定的,因此我們可以很自然的延展出這樣1個規則:對具有相同參數列表類型和返回值類型的函數,如果傳給函數1的參數類型一樣可以傳給函數2,而傳給函數2的參數未必都能傳給函數1,也就是說,只從參數部份考量,函數1可以被函數2替換,即函數1是父類,函數2 是子類。

對f2,我們說傳給它1個Animal實例它可以工作,傳給它1個Bird實例它依然可以工作,在傳給它1個Bird實例時,我們就要注意到,這時候的f2(僅看參數部份)實例的類型實際上就已變成f1了,這時候所有聲明使用f1類型的地方都可以用f2的實例去替換,但是反過來,所有聲明了使用f2類型的地方我們是不能用f1的實例去替換的,由于對f2來講,它可以接受Animal類型的任何其他子類型,比如Dog,但是Dog類型明顯不適用于f1的。所以總結起來,f1可以被f2替換,但是f2不能被f1替換,所以f1是f2的父類型!

讓我們再延伸地思考1下,我們可以說:由于f2是“消費”(consume)1個較為“通用”的父類型,這使得函數f2本身自然地能接納和處理給定參數類型的所有子類型,也就意味著f2可以去替換或賦值給那些所有聲明使用“具體”子類型為參數的函數,比如f1, 所以f1是父類,f2是子類!這類“消費”關系決定了逆變存在的理由,可以表述為PECS原理:

PECS stands for producer-extends, consumer-super.
In other words, if a parameterized type represents a T producer, use <? extends T>;
if it represents a T consumer, use <? super T>.

上述PECS原則換1種方法表述為:

G[+A]類似1個生產者,提供數據。(大部份情況下稱G為容器類型)
G[-A] 是1個消費者,主要用來消費數據。(參考垃圾桶和垃圾的例子)

雖然我們仍然在使用里氏替換原則來分析和辨認“逆變”的場景,但是我們不能不承認這類解釋仍然只是1種邏輯上的逆推,它的解釋總是讓人覺得不是那末“解癢”,在本文的最后,我試圖從正面給出1種“逆變”公道性的解釋:

**我們說在現實世界里,如果有1類物品專門針對另外一類物品而存在,除人們1般認為的伴隨著被處理物品的細化,處理品本身需要不斷地跟進細化,這是“協變”的場景,也確切有可能會存在另外1種完全相反的情形:即伴隨著被處理物品的細化,在掌握了愈來愈多處被理物品的信息和特點的趨勢下,處理物品本身卻可以變的愈發的簡單(處理面變窄),反倒是那些處理更通用物品的處理類復雜的多,由于它們要斟酌的可能的情況更多更復雜,那末這類情形就是典型的“逆變”!

1個典型是例子是空調和遙控器,如果說遙控器是基于空調類型的范型類,那末它天然應當是逆變的,即:RemoteController[-T], 空調品牌和型號越細化,遙控器實際上越單1,實現起來也越簡單,反倒是隨著空調類型不斷地向上抽象,遙控器會變得越加復雜,直到面向所有空調通用的遙控器RemoteController[AirConditioner]誕生,這也就是我們見到過的那種萬能遙控器。萬能遙控器可以替換任何品牌和型號的遙控器,因此它是它們的子類!

我們可以看到大多數的逆變類有以下1些特點:

  • 如果逆變類有1個類族,那末這個類族不會是自上而下的樹狀結構,而是多條單線繼承的路徑組合,比如:RemoteController[AirConditioner] <: RemoteController[Haier]; RemoteController[AirConditioner] <: RemoteController[Gree]等等
  • 逆變類的父類和子類雖然作為父類和子類有替換關系,但是卻沒有任何繼承關系,逆變類的子類之所以能夠替換父類常常是它涵蓋了父類的功能(針對某個更具體形變類型實現功能),而不存在繼承父類實現的動作,因此逆變類的子類實現起來反而更加復雜。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 视频日韩p影院永久免费 | 亚洲天堂.com | 中文字幕日韩精品中文区 | 看性过程三级视频在线观看 | 亚州一级毛片 | 欧美性视频在线播放 | 曰本老妇bbbbbxxxxx | 麻豆精选传媒4区2021 | 欧美日韩国产中文字幕 | 欧美精品一区二区三区视频 | 久久久亚洲精品国产 | 综合毛片 | 日韩一级视频免费观看 | 中文国产 | 高清在线观看视频 | 精品一区二区三区视频在线观看免 | 女人16一毛片 | 免费观看黄色网址 | 欧美成人精品不卡视频在线观看 | 波多野结衣免费在线视频 | 亚洲精品一区二区三区五区 | h小视频在线观看网 | 欧美超清性videosfree | 中文字幕亚洲综合精品一区 | 综合网站 | 国产 日韩 欧美 亚洲 | 亚洲欧美一区二区三区另类 | 久久天天躁狠狠躁夜夜爽蜜月 | 另类小说综合网 | 亚洲国内| 日韩国产欧美在线观看一区二区 | japanesexxx在线播放 | 色琪琪永久远网址 | 国产a毛片| 中文字幕日本不卡一二三区 | 美国jizz| 国产欧美成人免费观看 | 最近中文免费字幕在线播放 | 在线播放69热精品视频 | tube日本黑人杂交 | 久久做|