問題復現:
首先有乙個point類,重寫了equals方法:
public class point
@override public boolean queals(object o)
point p = (point)o;
return p.x == x && p.y == y;
}}
另有乙個擴充套件類,colorpoint繼承point類
public class colorpoint
}
這時候比較兩個點的時候就有個問題:
point point = new point(1, 2);
colorpoint cpoint = new colorpoint(1, 2, color.red);
system.out.println(point.equals(cpoint)); // true
system.out.println(cpoint.equals(point); // false
可以發現equals方法違背了對稱性原則,原因是point的equals方法在接收colorpoint型別的引數時,會將其當做point進行比較,忽略了顏色的判斷,認定兩個類是相等的。
對此我們做出一些修改:
此時可修改equals方法,加入對顏色的判斷:
if(!(o.instanceof(point))
return false;
//if o is a normal point,ignore color
if(!(o.instanceof(colorpoint))
return o.equals(this);
//if o is a colorpoint .do a full compation
return super.equals(o) && ((colorpoint)o).equals(this.color);
這段**修復了違背對稱性的錯誤,但兩個以上的點會有錯誤,比如 兩個colorpoint和乙個point作比較,如下:
colorpoint cpointred = new colorpoint(1, 2, color.red);
point point = new point(1, 2);
colorpoint cpointblue = new colorpoint(1, 2, color.blue);
system.out.println(cpointred.equals(point)); // true
system.out.println(point.equals(cpointblue)); // true
system.out.println(cpointred.equals(cpointblue)); // false
這樣又違背了傳遞性原則。這時候就有個建議:復合優先於繼承
。
即不使用繼承方式,而將'父類'包含在'子類'中
public class colorpoint
public point getpoint()
//重寫equals
@override public boolean equals(object o)
colorpoint cp = (colorpoint)o;
//只有當座標和顏色都相同才返回true;
return cp.point.equals(this.point) && cp.color.equals(color);
}}
當然,重寫equals的時候一定記得重寫hashcode~重寫hashcode~重寫hashcode~~de~de~de~ 第16條 復合優先於繼承
這裡的繼承是實現繼承而非介面繼承。與方法呼叫不同的是,繼承打破了封裝性 換句話說,子類依賴於其超類中特定功能的實現細節。超類的實現有可能會隨著髮型版本的不同而發生改變,如果真的發生了變化,子類可能會遭到破壞,即使他的 完全沒有改變。因此,子類必須跟著超類的更新而改變,除非超類是專門為擴充套件而設計的...
Java程式設計之 復合優先於繼承
組合 通過建立乙個由其他物件組合的物件來獲得新功能的重用方法 新功能的獲得是通過呼叫組合物件的功能實現的 有時又叫聚合 例如 乙個物件擁有或者對另外乙個物件負責並且兩個物件有相同的生命週期。gof 乙個物件包含另乙個物件集合 被包含物件對其他物件是不可見的並且只能從包含它的物件中訪問的特殊組合形式 ...
java 繼承 重寫
package inheritance.override 1 先開闢空間 2 再呼叫構造器 父類宣告賦值 父類構造器 子類宣告賦值 子類構造器 3 返回位址 屬性 就近原則 父類中的方法 如果重寫 找重寫,沒有重寫 找父類 新增不可見 先編譯後執行 編譯 從 所屬的當前類中向上找object 就近最...