日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

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

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

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

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]等等
  • 逆變類的父類和子類雖然作為父類和子類有替換關系,但是卻沒有任何繼承關系,逆變類的子類之所以能夠替換父類常常是它涵蓋了父類的功能(針對某個更具體形變類型實現功能),而不存在繼承父類實現的動作,因此逆變類的子類實現起來反而更加復雜。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 亚洲三区四区 | 麻豆国产一区二区三区四区 | 91露脸的极品国产系列 | 国产一级黄色毛片 | 成年网站在线观看 | 亚洲精品国产视频 | 一级黄视频 | 亚洲国产精品成人 | 日韩视频专区 | 日韩精品免费在线观看 | a黄色网| 国产精品国产精品国产专区不蜜 | 日本一区二区在线视频 | 日韩在线视频播放 | 日韩城人免费 | 精品一区在线 | 精品国产凹凸成av人导航 | 欧美成人性生活视频 | 国产91在| 亚洲电影中文字幕 | 99久久精品国产一区二区三区 | 精品欧美一区二区三区在线观看 | 日本中文字幕在线播放 | 尤物网站在线 | 免费爱爱视频 | 亚洲欧美综合精品久久成人 | 超碰999| 成人欧美一区二区三区视频网页 | 国产日产久久高清欧美一区 | 日韩久久久| 国产精品久久久久久久va果冻 | 成人一区二区三区四区 | 精品久久久久久久久久久下田 | 久久亚洲精品国产日韩潮高 | 国产精品一区二区av日韩在线 | 亚洲精品不卡 | 国内最真实的xxxx人伦 | 激情欧美亚洲 | 国产精品视频一区二区三区四区五区 | 亚洲专区久久 | 日韩欧美影院 |