2015-07-27 7 views
7

In dem Buch "Core Java Volume 1", die ich lese es sagt, die Gleichheit sollte nicht mit Vererbung arbeiten. Also, ich habe folgendes Beispiel, das etwas schief geht zu haben scheint:Was ist falsch an der Verwendung der Vererbungsgleichheit in Java?

public class Main { 

    public static void main(String[] args) { 

     C c = new C("Test", 10); 
     D d = new D("Test", 10); 

     if (c.equals(d)) 
      System.out.println("Equal"); 
     else 
      System.out.println("Unequal"); 

     if (d.equals(c)) 
      System.out.println("Equal"); 
     else 
      System.out.println("Unequal"); 
    } 
} 


class C 
{ 
    C(String cstr, int cnum) { 
     str = cstr; 
     num = cnum; 
    } 

    @Override 
    public boolean equals(Object otherObject) { 

     // A quick test to see if the objects are identical. 
     if (this == otherObject) { 
      return true; 
     } 

     // Must return false if the explicit parameter is null 
     if (otherObject == null) 
     { 
      return false; 
     } 

     if (!(otherObject instanceof C)) 
      return false; 

     // Now we know otherObject is a non-null Employee 
     C other = (C) otherObject; 

     // Test whether the fields have identical values 
     return str.equals(other.str) && num == other.num; 
    } 

    private String str; 
    private int num; 
} 

class D extends C { 

    D(String cstr, int cnum) { 
     super(cstr, cnum); 
    } 
} 

http://ideone.com/PhFBwG

Es gibt „Equal“ für beide symmetrischen Vergleiche, die vermutlich sollte es nicht. Fehlt eine weitere equals Methode in der abgeleiteten Klasse 'D'? Wenn ja, was könnte falsch mit oben genannten Beispielcode, wenn ich nicht einen anderen equals in überhaupt abgeleitet habe?

+0

"// Jetzt wissen wir, OtherObject ist ein Nicht-Null-Mitarbeiter" - sollte - Nun wissen wir, OtherObject ist ein Nicht-Null-Mitarbeiter oder eine Nicht-Null-Unterklasse von Employee. – Scooter

Antwort

4

Dieser Code funktioniert, weil, wie Sie gesagt haben, nicht equals überschreiben. Ich erwarte, dass der Punkt, das Buch zu machen, ist, dass Dsollte Überschreibung equals (und sie sollen beide außer Kraft setzen hashCode), weil eine D Instanz nicht mit einer C Instanz gleich sein sollte, da sie anders sind (wenn auch verwandte) Typen.

Denken Sie daran, dass einer der Schlüsselaspekte von the equals contractSymmetrie ist. Für alle nicht null Werte von c und d, wenn c.equals(d) ist wahr, dann muss d.equals(c) muss wahr sein (und die Umkehrung). Während das in Ihrem aktuellen Code wahr ist, sollte es wahrscheinlich nicht sein, denn und C sind unterschiedliche Typen. Wenn eine Instanz wirklich entspricht zu einer C Instanz ist, warum ?

4

Wenn Sie Instanzen C und D nicht als gleichwertig ersetzen !(otherObject instanceof C) mit otherObject.getClass() != this.getClass() zu vergleichen. Dies würde sicherstellen, dass nur ein C jemals einem anderen C entsprechen könnte und nur ein könnte jemals einem anderen gleich sein.

Ob Sie das wollen, hängt von ein paar Faktoren ab. Meine allgemeine Faustregel ist, dass es eine schlechte Idee ist, eine "offene" Gleichheitsklasse zu haben, wo "externe Benutzer" (was auch immer das für Sie bedeutet) hinzugefügt werden können. Wenn Sie möchten, dass Objekte verschiedener Typen als gleichwertig verglichen werden (und das ist selten genug), sollte die Hierarchie streng kontrolliert werden (z. B. mit Klassen final).

Sammlungen (und ähnlich gut definierte Schnittstellen) sind unterschiedlich: hier definiert die Schnittstelle einen sehr präzisen Vertrag, den alle implementierenden Klassen befolgen müssen (dh eine ArrayList kann einer LinkedList entsprechen, wenn sie beide die gleichen Elemente in der gleiche Reihenfolge, weil die List Schnittstelle definiert, was es für zwei List s bedeutet, gleich zu sein).

Verwandte Themen