Подтвердить что ты не робот

Почему абстрактный класс заставляет конкретный метод быть переопределенным?

Я использую библиотеку, где абстрактный класс переопределяет конкретный метод, унаследованный от 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)? Я не вижу цели этого.

4b9b3361

Ответ 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 без блока реализации позволит вам сделать это.