av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

從Scala看canEqual與正確的的equals實(shí)現(xiàn)

Equals實(shí)現(xiàn)在Java中有著很多的問(wèn)題(詳見(jiàn)《所有的Equals方法實(shí)現(xiàn)都是錯(cuò)誤的》),不過(guò)這些問(wèn)題并非令人完全喪氣。下面通過(guò)Scala作者的一篇文章中探討equals實(shí)現(xiàn)以及canEqual的使用。

創(chuàng)新互聯(lián)網(wǎng)站建設(shè)由有經(jīng)驗(yàn)的網(wǎng)站設(shè)計(jì)師、開(kāi)發(fā)人員和項(xiàng)目經(jīng)理組成的專業(yè)建站團(tuán)隊(duì),負(fù)責(zé)網(wǎng)站視覺(jué)設(shè)計(jì)、用戶體驗(yàn)優(yōu)化、交互設(shè)計(jì)和前端開(kāi)發(fā)等方面的工作,以確保網(wǎng)站外觀精美、成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè)易于使用并且具有良好的響應(yīng)性。

在 Effective Java 中,Joshua Bloch 提到,如果一個(gè)可實(shí)例化的類定義了 equals 方法。另有一個(gè)子類繼承它,也定義了額外一些屬性,并且 equals 方法中需要使用這些新定義的屬性進(jìn)行相等性判斷。那么就不可能保證 equals 語(yǔ)義的正確。

相信看過(guò) Effective Java 的人當(dāng)年讀到這里時(shí)都會(huì)覺(jué)得喪氣。就好像完美的世界突然有了一個(gè)無(wú)法縫合的裂口。先不要完全喪失興趣,看看下面的文章:

How to Write an Equality Method in Java (曾翻譯此文為《所有的Equals方法實(shí)現(xiàn)都是錯(cuò)誤的》)

這篇主要由 Scala 的作者 Martin Odersky 執(zhí)筆的文章中提到了一個(gè)有意思的方法。每個(gè)類在定義 equals 時(shí),首先先判斷 canEqual 能不能校驗(yàn)通過(guò)。canEqual 的作用就是限定:只有當(dāng)被比較的對(duì)象是當(dāng)前對(duì)象的子類或同類時(shí)才能通過(guò)。

 
 
 
  1. class Point {
  2.   // 屬性定義
  3.   ...
  4.   boolean canEqual(Object other) {
  5.     return (other instanceof Point);
  6.   }
  7.   
  8.   @Override boolean equals(Object other) {
  9.     if (other instanceof Point) {
  10.       Point that = (Point) other;
  11.       if (that.canEqual(this) && ...) return true
  12.     }
  13.     return false
  14.   }
  15.   
  16. }

子類的定義與父類相似。

也就是說(shuō),在這樣的約定下,如果拿一個(gè)父類實(shí)例和子類實(shí)例用 equals 比較肯定會(huì)返回 false。關(guān)于這篇文章,有興趣的話可以看看相應(yīng)的討論。

討論主要集中在文章里的方法是否違背了 Liskov Substitution Principle (LSP),以及如果違背了那么這個(gè)問(wèn)題有多嚴(yán)重上。看過(guò)下面的分析后大家也許會(huì)覺(jué)得這種討論沒(méi)有太多意義。

我個(gè)人推薦這種 canEqual 方法。我說(shuō)“方法”而不說(shuō)“解決方案”是因?yàn)槲矣X(jué)得 Odersky 所描述的 equals 實(shí)現(xiàn)與 Bloch 本來(lái)所期望的 equals 邏輯模型并不一致。想像 Odersky 文章中的例子。有一個(gè)類 - 點(diǎn)(Point),及其子類 - 有色點(diǎn)(ColoredPoint)。如果一個(gè)有色點(diǎn)實(shí)例,其坐標(biāo)與一個(gè)普遍點(diǎn)坐標(biāo)一樣,又因?yàn)橛猩c(diǎn)“是”點(diǎn),所以這兩點(diǎn)應(yīng)該“相等”。大家都期望這樣一個(gè)結(jié)論是成立的,所以當(dāng)看到 Bloch 的結(jié)論時(shí)會(huì)覺(jué)得面向?qū)ο笥衅涔逃械淖韵嗝苤?。但是這樣一個(gè)結(jié)論卻并不是天然成立的。一個(gè)沒(méi)有顏色的點(diǎn)與一個(gè)有顏色的點(diǎn)能相等嗎?有人會(huì)說(shuō),如果 ColoredPoint 里面的 color 屬性是一個(gè)枚舉,而且那個(gè)子類被實(shí)例化成 Color.UNSPECIFIED(未指定的顏色),那么這兩個(gè)點(diǎn)邏輯上就應(yīng)該相等了吧。我認(rèn)為,如果 ColoredPoint.color 可以有這樣一個(gè)屬性值的話,那么 Point 類就應(yīng)該被定義為抽象類。Point 類此時(shí)實(shí)例化沒(méi)有意義。換句話說(shuō),如果 Point 類可以實(shí)例化,且其子類 ColoredPoint 也可以有一個(gè)“未指定的顏色”,而且兩者都定義了 equals,那么出現(xiàn)這種情況我認(rèn)為是設(shè)計(jì)失敗。

再看看 LSP。LSP 說(shuō),任何可以使用父類實(shí)例的地方都可以使用子類實(shí)例代替。這里并不違反 LSP,因?yàn)槿绻粋€(gè)地方可以這樣調(diào)用:

 
 
 
  1. Point p = new Point();
  2. if (p.equals(...)) {
  3.   ...
  4. }

那么使用子類一樣可以調(diào)用 equals。只不過(guò),equals 在傳入相同的參數(shù)時(shí)返回的結(jié)果可能會(huì)不一樣。但是 LSP 并不約束必須返回一樣的結(jié)果。而這正是多態(tài)的特征。

回到 Bloch 的論點(diǎn)上。現(xiàn)在贊同我的人可能會(huì)覺(jué)得 Bloch 的論點(diǎn)有問(wèn)題。其實(shí)他說(shuō)得很嚴(yán)謹(jǐn),沒(méi)有一絲問(wèn)題。他的論點(diǎn)的前提是:可實(shí)例化的父類。也就是說(shuō)無(wú)法針對(duì)非抽象類寫出滿足大家傳統(tǒng)期望的子類。只不過(guò),另人失望地,他在提出這個(gè)結(jié)論后沒(méi)有給出對(duì)應(yīng)的方法。相對(duì)來(lái)說(shuō),Odersky 理清了 Bloch 的邏輯模型。所以,在 Odersky 所發(fā)明的 Scala 中,canEqual 這個(gè)方法也被作為官方推薦的 equals實(shí)現(xiàn)方法。


本文標(biāo)題:從Scala看canEqual與正確的的equals實(shí)現(xiàn)
網(wǎng)頁(yè)地址:http://uogjgqi.cn/article/djceedo.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流