#java #oop #inheritance
#java #ооп #наследование
Вопрос:
У меня есть родительский класс Animal, который наследуется классом Dog
public class Animal {
private String color;
private Boolean hasTail;
private Integer legs;
public Animal(String color, Boolean hasTail , Integer legs){
this.color = color;
this.hasTail = hasTail;
this.legs = legs;
}
protected void speak(){
System.out.println("the animal is speaking");
sleep();
}
public void sleep(){
System.out.println("The animal is sleeping");
}
}
public class Dog extends Animal {
public Dog(String name) {
super("Black", true, 12);
this.name = name;
}
private String name;
public void bark() {
System.out.println("bow bow bow");
super.speak();
}
public void sleep(){
System.out.println("The Dog is sleeping");
}
}
и когда я делаю
Dog d = new Dog("tommy");
d.bark();
результат таков
bow bow bow
the animal is speaking
The Dog is sleeping
но я ожидал, что результат будет
bow bow bow
the animal is speaking
The animal is sleeping
итак, кто-нибудь может, пожалуйста, подробно объяснить, как это происходит? поскольку класс Animal должен вызывать метод sleep своего собственного класса, а не класса Dog, это то, что у меня сложилось впечатление, а также как это узнать, унаследовал ли его какой-либо класс?
ПРАВКА 1: — если я изменю метод sleep в классе Animal с public на private, то я получаю второй результат.Объект по-прежнему относится к типу Dog, так почему же он теперь выдает второй вывод?
Комментарии:
1. Вы создаете экземпляр a,
new Dog()
иDog
класс реализуетsleep()
. Вот почему версия выполняемого метода — это версия в классе Dog. Попробуйте создать экземплярAnimal animal = new Animal()
иAnimal animal2 = new Dog()
и посмотрите, как они себя ведут.
Ответ №1:
При вызове метода sleep из speak
, поскольку ваш объект принадлежит классу Dog, очевидно, что он вызовет метод sleep из Dog class
.
Если вы хотите вызвать метод sleep класса Animal, то просто поместите super.sleep
в метод Dog’s sleep.
public void sleep(){
super.sleep();
}
Комментарии:
1. ~ Сагар Гангвал когда я меняю тип доступа sleep на private в классе Animal, я получаю второй вывод. Даже сейчас объект имеет тип Dog class .
2. Поскольку вы знаете о области действия
private
, это относится только к этому классу. Таким образом, в этом случаеsleep
методAnimal
Dog
не виден в в классе.
Ответ №2:
Вы переопределили sleep и не говорите.
Итак, когда вы создаете экземпляр Dog , он использует метод Animal speak (поскольку он не переопределен в Dog), но также использует метод Dog sleep, поскольку он перезаписывается.
Если вы хотите достичь своей цели, вы должны сделать :
public class Dog extends Animal {
public Dog(String name) {
super("Black", true, 12);
this.name = name;
}
private String name;
public void bark() {
System.out.println("bow bow bow");
super.speak();
}
public void sleep(){
super.sleep();
System.out.println("The Dog is sleeping");
}
}
И тогда у вас будет
bow bow bow
the animal is speaking
The animal is sleeping
The Dog is sleeping
Вы понимаете?
Ответ №3:
Вызов с помощью super имеет смысл только тогда, когда вы хотите вызвать родительский метод, когда есть также дочерний метод с тем же именем (т. Е. Переопределение родительского метода). Dog не имеет, speak()
поэтому super в super.speak()
является избыточным. Вызовите speak()
сам по себе и получите тот же результат.
Чтобы ответить на 2-ю часть:
Изменение метода на private означает, что он виден только своему собственному классу. Родительский метод sleep()
теперь не может быть виден дочернему, что означает, что дочерний метод sleep()
теперь является отдельным методом, а не переопределением.
Если вы попытаетесь вызвать дочерний метод (т. Е. не переопределяющий) из родительского метода, он не будет компилироваться. Протестируйте, вызвав bark()
из speak()
.
Ваш вызов метода sleep()
в этом примере привязывается к методу, который имеет смысл, к частному методу в Animal.