Я не понимаю, чем переопределение отличается от скрытия в Java. Кто-нибудь может предоставить более подробную информацию о том, чем они отличаются? Я прочитал руководство по Java, но пример кода все еще оставил меня в замешательстве.
Чтобы быть более понятным, я хорошо понимаю переопределение. Моя проблема в том, что я не вижу, чем скрытие отличается, за исключением того факта, что одно находится на уровне экземпляра, а другое - на уровне класса.
Для меня тот факт, что вызов метода класса testClassMethod() непосредственно из Animal класса выполняет метод в Animal классе, довольно очевиден, в этом нет ничего особенного. Затем они вызывают testInstanceMethod() из ссылки на myCat, так что опять же довольно очевидно, что выполняемый тогда метод является тем, который находится в экземпляре Cat.
Из того, что я вижу, скрытие вызова ведет себя точно так же, как переопределение, так зачем делать это различие? Если я запускаю этот код, используя классы выше:
Cat.testClassMethod();
Я получу: Метод класса в Cat. Но если я удалю testClassMethod() из Cat, то я получу: Метод класса в Animal.
Который показывает мне, что написание статического метода с той же сигнатурой, что и у родительского, в подклассе в значительной степени переопределяет.
Надеюсь, я проясняю, где я запутался, и кто-нибудь сможет пролить свет. Заранее большое спасибо!
Переведено автоматически
Ответ 1
Переопределение в основном поддерживает позднее связывание. Следовательно, во время выполнения решается, какой метод будет вызван. Это для нестатических методов.
Скрытие предназначено для всех остальных членов (статических методов, членов экземпляра, статических членов). Оно основано на ранней привязке. Более очевидно, что метод или элемент, который будет вызываться или использоваться, определяется во время компиляции.
В вашем примере первый вызов, Animal.testClassMethod() это вызов static метода, следовательно, вы почти уверены, какой метод будет вызван.
Во втором вызове, myAnimal.testInstanceMethod(), вы вызываете нестатический метод. Это то, что вы называете полиморфизмом во время выполнения. До времени выполнения не решено, какой метод вызывать.
Статические методы скрыты, нестатические методы переопределены. Разница заметна, когда вызовы не квалифицируются как "something()" по сравнению с "this.something()".
Кажется, я действительно не могу выразить это словами, поэтому приведу пример:
publicAnimal() { // This will always call Animal.something(), since it can't be overriden, because it is static. something(); // This will call the eat() defined in overriding classes. eat(); }
}
publicclassDogextendsAnimal {
publicstaticvoidsomething() { // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way. System.out.println("dog.something"); }
publicvoideat() { // This method overrides eat(), and will affect calls to eat() System.out.println("dog.eat"); }
publicDog() { super(); }
publicstaticvoidmain(String[] args) { newDog(); }
}
ВЫВОД:
animal.something dog.eat
Ответ 3
В этом разница между переопределениями и скрытием,
Если оба метода в родительском классе и дочернем классе являются методом экземпляра, он вызывает переопределения.
Если оба метода в родительском классе и дочернем классе являются статическими, это вызывает скрытие.
Один метод не может быть статичным в родительском и как экземпляр в дочернем. и наоборот.
Ответ 4
Если я правильно понял ваш вопрос, то ответ будет "вы уже переопределяете".
"Который показывает мне, что написание статического метода с тем же именем, что и у родительского, в подклассе в значительной степени приводит к переопределению".
Если вы напишете метод в подклассе с точно таким же именем, что и у метода в суперклассе, он переопределит метод суперкласса. Аннотация @Override не требуется для переопределения метода. Однако это делает ваш код более читабельным и заставляет компилятор проверять, что вы на самом деле переопределяете метод (и не допустили ошибок в написании метода подкласса, например).