Вопрос-ответ

Overriding vs Hiding Java - Confused

Переопределение против скрытия Java - Запутано

Я не понимаю, чем переопределение отличается от скрытия в Java. Кто-нибудь может предоставить более подробную информацию о том, чем они отличаются? Я прочитал руководство по Java, но пример кода все еще оставил меня в замешательстве.

Чтобы быть более понятным, я хорошо понимаю переопределение. Моя проблема в том, что я не вижу, чем скрытие отличается, за исключением того факта, что одно находится на уровне экземпляра, а другое - на уровне класса.

Знакомство с кодом руководства по Java:

public class Animal {
public static void testClassMethod() {
System.out.println("Class" + " method in Animal.");
}
public void testInstanceMethod() {
System.out.println("Instance " + " method in Animal.");
}
}

Тогда у нас есть подкласс Cat:

public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The class method" + " in Cat.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Cat.");
}

public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}

Затем они говорят:


Вывод этой программы выглядит следующим образом:


Метод класса в Animal .


Метод экземпляра в Cat.


Для меня тот факт, что вызов метода класса testClassMethod() непосредственно из Animal класса выполняет метод в Animal классе, довольно очевиден, в этом нет ничего особенного. Затем они вызывают testInstanceMethod() из ссылки на myCat, так что опять же довольно очевидно, что выполняемый тогда метод является тем, который находится в экземпляре Cat.

Из того, что я вижу, скрытие вызова ведет себя точно так же, как переопределение, так зачем делать это различие? Если я запускаю этот код, используя классы выше:

Cat.testClassMethod();

Я получу:
Метод класса в Cat.
Но если я удалю testClassMethod() из Cat, то я получу:
Метод класса в Animal.

Который показывает мне, что написание статического метода с той же сигнатурой, что и у родительского, в подклассе в значительной степени переопределяет.

Надеюсь, я проясняю, где я запутался, и кто-нибудь сможет пролить свет. Заранее большое спасибо!

Переведено автоматически
Ответ 1

Переопределение в основном поддерживает позднее связывание. Следовательно, во время выполнения решается, какой метод будет вызван. Это для нестатических методов.

Скрытие предназначено для всех остальных членов (статических методов, членов экземпляра, статических членов). Оно основано на ранней привязке. Более очевидно, что метод или элемент, который будет вызываться или использоваться, определяется во время компиляции.

В вашем примере первый вызов, Animal.testClassMethod() это вызов static метода, следовательно, вы почти уверены, какой метод будет вызван.

Во втором вызове, myAnimal.testInstanceMethod(), вы вызываете нестатический метод. Это то, что вы называете полиморфизмом во время выполнения. До времени выполнения не решено, какой метод вызывать.

Для получения дополнительных разъяснений прочитайте Переопределение против скрытия.

Ответ 2

Статические методы скрыты, нестатические методы переопределены. Разница заметна, когда вызовы не квалифицируются как "something()" по сравнению с "this.something()".

Кажется, я действительно не могу выразить это словами, поэтому приведу пример:

public class Animal {

public static void something() {
System.out.println("animal.something");
}

public void eat() {
System.out.println("animal.eat");
}

public Animal() {
// 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();
}

}


public class Dog extends Animal {

public static void something() {
// 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");
}

public void eat() {
// This method overrides eat(), and will affect calls to eat()
System.out.println("dog.eat");
}

public Dog() {
super();
}

public static void main(String[] args) {
new Dog();
}

}

ВЫВОД:

animal.something
dog.eat
Ответ 3

В этом разница между переопределениями и скрытием,


  1. Если оба метода в родительском классе и дочернем классе являются методом экземпляра, он вызывает переопределения.

  2. Если оба метода в родительском классе и дочернем классе являются статическими, это вызывает скрытие.

  3. Один метод не может быть статичным в родительском и как экземпляр в дочернем. и наоборот.

введите описание изображения здесь

Ответ 4

Если я правильно понял ваш вопрос, то ответ будет "вы уже переопределяете".

"Который показывает мне, что написание статического метода с тем же именем, что и у родительского, в подклассе в значительной степени приводит к переопределению".

Если вы напишете метод в подклассе с точно таким же именем, что и у метода в суперклассе, он переопределит метод суперкласса. Аннотация @Override не требуется для переопределения метода. Однако это делает ваш код более читабельным и заставляет компилятор проверять, что вы на самом деле переопределяете метод (и не допустили ошибок в написании метода подкласса, например).

java inheritance