Java Slayer – Equals Slayer – rozwiązanie
Paweł był blisko, a i ja tworzyłem to zadanie z myślą panu J Blochu. Problem z kodem jest jednak troszkę inny. Pisząc metodę equals musi ona spełniać kilka podstawowych zasad. Jedną z nich jest symetryczność, czyli a.equals(b) == b.equals(a).
Przy dziedziczeniu oznacza to, że dobrze by było żeby jeżeli b rozszerza a to działanie equals w b uwzględnia ten fakt. Dodatkowo mamy tu zasadę Liskov, która mówi, że pod klasa powinna zachowywać się jak nad klasa. Czyli b powinno być w stanie porównać się z a tak jakby było a.
Ok w czym problem. Otóż nigdy nie będzie wywołane tak naprawdę porównanie ColorPoint. ColorPoint jest instancją Point zatem niezależnie jaki obiekt (ColorPoint, czy Point) będziemy porównywać to zostanie zwrócony wynik z linii 79.
Prawidłowa implementacja powinna wyglądać w następujący sposób:
Listing 1. Prawidłowa implementacja metody ColorPoint.equals
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Point))
return false;
if (obj instanceof ColorPoint){
ColorPoint p = (ColorPoint) obj;
return super.equals(obj) && this.color.equals(p.color);
}
if (obj instanceof Point)
return super.equals(obj);
return false;
}
W tym przypadku najpierw sprawdzimy czy obiekt należy do bardziej szczegółowej klasy, a dopiero potem czy jest bardziej ogólny. Dobrze napisana metoda equals powinna tego typu sprawdzenia wykonywać od liścia do korzenia.