2015-06-17 14 views
19

używam biblioteki gdzie klasa abstrakcyjna zasłania konkretną metodę odziedziczoną Object z abstrakcyjnej metody:Dlaczego klasa abstrakcyjna może wymusić zastąpienie konkretnej metody?

public abstract class A { 
    @Override 
    public abstract boolean equals(Object obj); 
} 

przedłużyć tę klasę, trzeba zaimplementować metodę equals:

public class B extends A { 
    @Override 
    public boolean equals(Object obj) { 
     return obj != null && obj.getClass() == B.class; 
    } 
} 

Dlaczego metoda abstrakcyjna (A::equals) zastępuje konkretną metodę (Object::equals)? Nie widzę tego celu.

+1

Jest odwrotnie - klasa bazowa ma metodę abstrakcyjną, a klasa pochodna nie abstrakcyjna ma nie abstrakcyjną metodę, która zastępuje metodę klasy podstawowej. – sharptooth

+1

@sharptooth Moje pytanie nie było zbyt jasne. Mówię o 'A :: equals' overriding' Object :: equals' – gontard

+0

Sądzę, że powinieneś wyraźnie to wyrazić w pytaniu. Ponieważ przedstawiłeś tylko dwie swoje klasy, byłem pewien, że pytanie dotyczyło tylko ich. – sharptooth

Odpowiedz

24

W tym konkretnym przykładzie ma to sens. Jeśli podklasy A mają być używane w kolekcjach, gdzie equals jest powszechnie używany do lokalizowania obiektów, abstrakcyjne metody A wymuszają podanie domyślnej implementacji equals w dowolnej podklasie A (zamiast przy użyciu domyślnej implementacji klasy Object, która tylko porównuje odwołania do instancji).

Oczywiście sugerowana implementacja equals w B nie ma większego sensu. Powinieneś porównywać właściwości wystąpień 2 B, aby określić, czy są one równe.

To jest bardziej odpowiednia realizacja:

public class B extends A { 
    @Override 
    public boolean equals(Object obj) { 
     if (!(obj instanceof B)) 
      return false; 
     B other = (B) obj; 
     return this.someProperty.equals(other.someProperty) && this.secondProperty.equals(other.secondProperty); 
    } 
} 

Ponadto, należy pamiętać, aby zastąpić hashCode ilekroć przesłonić equals (od umowy equals i hashCode wymaga, że ​​jeśli a.equals(b) == true następnie a.hashCode() == b.hashCode()).

+0

Jeśli' B' nie ma innych właściwości (i nie ma 'A'), które sprawiają, że instancje różnią się od siebie, wdrożenie takie jak w pytaniu może być sensowne. Chociaż porównanie z instancją 'this.getClass()' klasy B. byłoby bardziej poprawne, biorąc pod uwagę podklasy 'B'. –

+0

Tak, może "B" to Singleton – acbabis

10

Ponieważ w tym przypadku użytkownik chciałby, aby obiekty definiowały własne obiekty equals, które podobno będą działać inaczej niż domyślna implementacja.

Nie należy patrzeć na to jako na funkcję , usuwając funkcję, ale raczej na wymuszanie, że dziedziczące obiekty implementują własne.

+0

Jesteś wyraźnie widzący, naprawdę widziałem to * jako usuwanie funkcjonalności *. – gontard

+0

@gontard: W tym przypadku * chcesz * zaimplementować klasy, aby określić własne zachowanie. Aby to zrobić, należy upewnić się, że domyślna implementacja nie jest dostępna, aby uzyskać pożądane zachowanie. – npinti

+0

Właściwie to [jest nadal dostępne] (http://stackoverflow.com/a/2692379/823393), ale wcale nie łatwo. – OldCurmudgeon

6

Umożliwia to wymuszenie podklasy w celu ponownego zastosowania metody. Czy to dobry pomysł, czy nie, to inna kwestia. Zrobiłbyś to tylko, gdybyś chciał egzekwować silniejszą umowę niż dostarczona oryginalna metoda. Następnie należy starannie udokumentować nową umowę.

3

Oznacza to, że musi zaimplementować własną equals() metodę

1

Ponieważ wszystkie klasy w Javie natury rozszerzyć klasę Object. Klasa A będzie dziedziczyć metodę Object#equals. Załóżmy, że chcesz wymusić błąd kompilacji, gdy metoda równań nie jest jawnie zaimplementowana, tak jak w tym example. Wykonanie abstrakcyjnej metody równań bez bloku implementacji umożliwiłoby to wykonanie.

Powiązane problemy