2015-06-17 3 views
19

Я использую библиотеку, где абстрактный класс переопределяет конкретный метод, унаследованный от Object с абстрактным способом:Почему абстрактный класс заставляет конкретный метод переопределяться?

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

Чтобы расширить этот класс, я должен реализовать equals метод:

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

Почему абстрактный метод (A::equals) переопределяет конкретный метод (Object::equals)? Я не вижу цели этого.

+1

Здесь обратное - базовый класс имеет абстрактный метод, а неабстрактный производный класс имеет не абстрактный метод, который переопределяет метод базового класса. – sharptooth

+1

@sharptooth Мой вопрос был не очень ясен. Я говорю о 'A :: equals' overriding' Object :: equals' – gontard

+0

Думаю, вы должны прямо сказать это в вопросе. Поскольку вы только представили два своих класса, я был уверен, что вопрос касается только их. – sharptooth

ответ

24

В этом конкретном примере это имеет смысл. Если подклассы A предназначены для использования в коллекциях, где equals широко используется для поиска объектов, то создание абстрактного метода Aequals приводит к тому, что вы даете нестандартную реализацию equals в любых подклассах A (вместо используя стандартную реализацию класса Object, которая сравнивает только примеры экземпляров).

Конечно, ваша предлагаемая реализация equals в B имеет мало смысла. Вы должны сравнивать свойства экземпляров 2 B, чтобы определить, равны ли они.

Это более подходит реализация:

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); 
    } 
} 

Кроме того, помните, чтобы переопределить hashCode всякий раз, когда вы переопределить equals (с договором equals и hashCode требует, что если a.equals(b) == true затем a.hashCode() == b.hashCode()).

+0

Если 'B' не имеет других свойств (и не имеет' A'), которые делают экземпляры разными друг от друга, реализация, как в вопросе, может быть разумной. Хотя сравнение с 'this.getClass()' экземпляром 'B.class' было бы более правильным при рассмотрении подклассов' B'. –

+0

Да, может быть, 'B' является Singleton – acbabis

10

Потому что в этом случае вы хотели бы, чтобы ваши объекты определяли свои собственные equals, которые предположительно будут отличаться от реализации по умолчанию.

Вы не должны смотреть на это как , удаляя функциональность, а скорее применяя к тому, чтобы наследующие объекты реализовывали свои собственные.

+0

Вы понятны, я действительно видел это * как удаление функциональности *. – gontard

+0

@gontard: В этом случае вы * хотите * реализовать классы, чтобы определить их собственное поведение. Для этого вам необходимо убедиться, что реализация по умолчанию недоступна, чтобы получить желаемое поведение. – npinti

+0

На самом деле он [по-прежнему доступен] (http://stackoverflow.com/a/2692379/823393), но совсем не легко. – OldCurmudgeon

6

Это позволит вам подставить подкласс для переопределения метода. Является ли это хорошей идеей или нет, другое дело. Вы сделали бы это только в том случае, если хотите применить более сильный контракт, чем оригинальный метод. Затем вы должны тщательно документировать новый контракт.

3

Это означает, что вы должны реализовать свой собственный метод equals()

1

Поскольку все классы в Java по своей сути расширить Object класс. Класс A наследует метод Object#equals. Предположим, вы хотите принудительно выполнить компиляцию, когда метод equals явно не реализован, как в этом example. Создание абстрактного метода equals без блока реализации позволит вам сделать это.

Смежные вопросы