Почему абстрактный класс заставляет конкретный метод быть переопределенным?
Я использую библиотеку, где абстрактный класс переопределяет конкретный метод, унаследованный от 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
В этом конкретном примере это имеет смысл. Если подклассы A предназначены для использования в коллекциях, где equals
широко используется для поиска объектов, создание абстрактного метода A
equals
приводит к тому, что вы даете нестандартную реализацию 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
требует, чтобы if a.equals(b) == true
, затем a.hashCode() == b.hashCode()
).
Ответ 2
Поскольку в этом случае вы хотели бы, чтобы ваши объекты определяли свой собственный equals
, который, предположительно, будет отличаться от реализации по умолчанию.
Вы не должны смотреть на это как на удаление функций, а на то, чтобы обеспечить, чтобы наследующие объекты реализовали свои собственные.
Ответ 3
Это позволит вам подставить подкласс для переопределения метода. Является ли это хорошей идеей или нет, другое дело. Вы сделали бы это только в том случае, если хотите применить более сильный контракт, чем оригинальный метод. Затем вы должны тщательно документировать новый контракт.
Ответ 4
Это означает, что должен реализовать собственный метод equals()
Ответ 5
Поскольку все классы в Java по существу расширяют класс Object. Класс A
наследует метод Object#equals
. Предположим, вы хотели принудительно выполнить компиляцию, когда метод equals явно не реализован, как в примере . Создание абстрактного метода equals без блока реализации позволит вам сделать это.