2012-09-02 19 views
10

Bir Java kitabını okuduğumda, yazar, bir sınıf tasarlarken, kalıtım ile equals()'u kullanmanın genellikle güvensiz olduğunu söylemiştir. Örneğin: Yukarıdaki sınıftaNeden miras ile eşitlik kullanmamalıyım?

public final class Date { 
    public boolean equals(Object o) { 
     // some code here 
    } 
} 

, biz final koymak gerekir, böylece diğer sınıf bundan devralamaz. Ve sorum şu ki, başka bir sınıfın buna izin verdiği zaman neden güvensiz olduğu?

+0

"Karşılaştırılabilir", "eşittir" değil, "Karşılaştırma" ifadesini belirtir. – oldrinb

+0

Oh. teşekkürler :) Düzenlediklerim: D – hqt

+0

Kitabın adı nedir? –

cevap

19

Özellikle symmetric property numaralı telefonu doğru yapmak zor çünkü (imkansız?).

Sınıf Vehicle sınıfına ve Car extends Vehicle sınıfına sahip olduğunuzu varsayalım. Vehicle.equals(), bağımsız değişken de Vehicle ise ve aynı ağırlığa sahipse true değerini verir.

Vehicle tank = new Vehicle(); 
Vehicle bus = new Car(); 
tank.equals(bus); //can be true 
bus.equals(tank); //false 

: Eğer Car.equals() uygulamak istiyorsanız vs.

Şimdi hayal, motor, yapmak Aşağıdaki kodu argüman ayrıca araç olması durumunda bu true vermelidir ve kilo hariç, o da karşılaştırmak gerekir İlk karşılaştırma, tesadüf tankı ve otobüsün aynı ağırlığa sahip olması durumunda true verebilir. Ancak tank bir araba olmadığından, bir araba ile kıyaslandığında her zaman false elde edilir. Sıkı

  • :

    Sen kaç alternatif çözüm ve sadece onlar tam olarak aynı tip (ve tüm özellikleri eşit) ise iki nesnenin eşittir. Bu kötü, ör. Bazı davranışlar eklemek veya orijinal sınıfı dekore etmek için alt sınıfı seçtiğinizde. Bazı çerçeveler, sizin de sınıflarınızı alt sınıflara ayırmadan farketmezler (Hibernate, Spring AOP, CGLIB proxy'leri ile ...)

  • gevşek: türleri "uyumlu" ise ve aynı içeriğe sahiplerse (semantik olarak) iki nesne eşittir. Örneğin. iki öğenin aynı öğeleri içermesi durumunda eşittir, birinin HashSet ve diğerinin TreeSet olması önemlidir (bunu belirtmek için @veer teşekkürler).

    Bu yanıltıcı olabilir. İki adet LinkedHashSet s'yi (ekleme siparişinin sözleşmenin bir parçası olduğu durumlarda) çekin. equals() sadece hesaba ham Set sözleşme sürer Ancak bu yana, karşılaştırma verimleri bile açıkça farklı nesneler için true:

    Set<Integer> s1 = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3)); 
    Set<Integer> s2 = new LinkedHashSet<Integer>(Arrays.asList(3, 2, 1)); 
    System.out.println(s1.equals(s2)); 
    

(Ayrıca bkz

+1

Not * imkansız *; bakınız örn. ['Set.equals'] (http://docs.oracle.com/javase/7/docs/api/java/util/Set.html#equals (java.lang.Object)) – oldrinb

+0

@veer: Güncelleme yaptım Cevap, teşekkürler. –

+0

@TomaszNurkiewicz senin link olarak, eğer eğer kullanalım, eğer if (this.getClass()! = Tank.getClass()) {return false;} 'or' if (this.getClass()! = Tank.getClass()) {return false;}, sorun çözülecek. Bana bu dava hakkında daha fazla bilgi verir misin? – hqt

8

Martin Odersky Java'da jeneriklerin arkasındaki adam ve geçerliiçin orijinal kod tabanı), bu sorunu ele alan Scala numaralı kitabında kitabında güzel bir bölüm var. canEqual yönteminin eklenmesi eşitlik/miras sorunu sorununu giderebilir.

Chapter 28 of Programming in Scala, First Edition: Object Equality

kitabı Scala atıfta elbette, ama aynı fikirleri klasik Java için geçerlidir: Eğer online olarak kullanılabilir kitabının ilk baskısında, tartışmayı okuyabilir. Örnek kaynak kodunun, Java arka planından gelen birinin anlaşılması çok zor olmamalıdır.

Düzenleme:

Odersky geri 2009 yılında Java aynı konsept üzerine bir makale yayınladı gibi görünüyor ve aynı web sitesinde mevcut: gerçekten

How to Write an Equality Method in Java

Ben Bu cevabın makalesini özetlemeye çalışmanın adalet yapmaz olduğunu düşünmeyin. Eşitlik uygulamalarında yapılan ortak hatalardan, eşdeğerlik ilişkisi olarak Java equals'un tam bir tartışmasına kadar, nesne eşitliği konusunu derinlemesine ele alır. Gerçekten sadece okumalısın.