Полиморфизм Java и сопоставление методов во время выполнения - PullRequest
0 голосов
/ 01 ноября 2018

Например, у меня есть следующий код.

class Circle {
    double radius;

    public boolean equals(Object circle) {
        return this.radius ==((Circle)circle).radius;
    }
}

и драйвер

public class Driver {
    public static void main(String[] args) {
        Object circle1 = new Circle();
        Circle circle2 = new Circle();
        System.out.println(circle1.equals(circle2));

    }
}

Он печатает True, но если я переписываю Circle.equals () как

public boolean equals(Circle circle) {
    return this.radius ==((Circle)circle).radius;
}

где метод .equals () принимает тип Circle, система выводит False.
Я знаю, что класс Circle является подклассом класса Object, поэтому компилятор не сообщает об ошибке, и во время выполнения JVM выбирает правильный метод переопределения для реализации правильного поведения. Если я изменю код как нижний, где .equals () принимает объекты класса Circle, Code может быть реализован правильно, пожалуйста, скажите мне, почему. Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

С подписью метода

public boolean equals(Circle circle) {

Вы перегружаете equals, не перекрывая его; это не ошибка компилятора. Это означает, что Circle унаследует реализацию Object equals, которая просто сравнивает ссылки на объекты, чтобы определить, равны ли они. Это возвращает false.

Ваш метод equals должен занять Object для правильного переопределения метода. Вам также следует использовать аннотацию @Override, которая приведет к ошибке компилятора, если аннотированный метод не переопределит метод в суперклассе. Тело meethod должно проверить, является ли его аргумент экземпляром класса перед приведением, поэтому оно может вернуть false вместо броска ClassCastException.

Кроме того, всегда полезно переопределить hashCode, если вы переопределяете equals.

0 голосов
/ 01 ноября 2018

В Java возвращаемые типы являются ковариантными, это означает, что вы можете использовать подкласс в качестве возвращаемого типа для переопределенного метода.
Например, это действительно:

public class Foo{
    @Override
    public Foo clone(){
        ...
    }
}

Но типы параметров не являются ковариантными. Таким образом, вы перегружаете метод во втором коде, вы не переопределяете его.

Аннотируйте метод с помощью @Override, и он больше не будет компилироваться:

@Override 
public boolean equals(Circle circle) {
    return this.radius ==((Circle)circle).radius;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...