class Mammal {
void eat(Mammal m) {
System.out.println("Mammal eats food");
}
}
class Cattle extends Mammal {
void eat(Cattle c) {
System.out.println("Cattle eats hay");
}
}
class Horse extends Cattle {
void eat(Horse h) {
System.out.println("Horse eats hay");
}
}
public class Test {
public static void main(String[] args) {
Mammal h = new Horse();
Cattle c = new Horse();
System.out.println(h + " " + c);
h.eat(c);
}
}
在此程序中,我正在为马创建对象,但输出仍然是
"Mammal eats food"
。
我希望输出为"Horse eats hay"
。
所以请有人可以帮我这个忙。
答案 0 :(得分:2)
要获得所需的输出,以下代码将起作用:
这是方法替代
class Mammal{
void eat(){
System.out.println("Mammal eats food");
}
}
class Cattle extends Mammal{
void eat(){
System.out.println("Cattle eats hay");
}
}
class Horse extends Cattle{
void eat(){
System.out.println("Horse eats hay");
}
}
public class Main{
public static void main(String[] args){
Mammal h = new Horse();
Cattle c = new Horse();
h.eat(); //Horse eats hay
c.eat(); //Horse eats hay
}
}
答案 1 :(得分:2)
您的覆盖概念不正确,您实际上所做的是方法重载。
仅当被覆盖的方法的签名相同时,覆盖才有效。通过方法签名,我们指的是方法名称和参数。
因此,在您的代码中,所有子类都应具有相同的方法签名。
void eat(Mammal m) {
System.out.println("xxx eats food");
}
但是方法重载和方法重载之间的重要区别在于它们的解析时间,因为在您的情况下,重载在编译时已解决,方法重载在运行时已解决。
因此,因为您使用了父类的引用来保存子类实例,所以在编译时通过查看引用的类型来确定父类的方法,因此总是会调用它。
要严格执行覆盖,请使用@Override
注释方法,如果覆盖未正确完成,则会导致编译时错误。在示例中,如果添加@Override
,则会看到编译时错误。
因此,将您的类更改为以下内容并查看区别:
class Mammal {
void eat(Mammal m) {
System.out.println("Mammal eats food");
}
}
class Cattle extends Mammal {
@Override
void eat(Mammal m) {
System.out.println("Cattle eats hay");
}
}
class Horse extends Cattle {
@Override
void eat(Mammal m) {
System.out.println("Horse eats hay");
}
}
public class Test {
public static void main(String[] args) {
Mammal h = new Horse();
Cattle c = new Horse();
System.out.println(h + " " + c);
h.eat(c);
}
}
输出将是:
Horse@60addb54 Horse@3f2a3a5
Horse eats hay
您可能会倾向于认为具有不同签名的方法不会重载,因为它们位于不同的类(继承)中,但是如果您在spec:
如果一个类的两个方法(是否都在同一个类中声明,或者 都由一个类继承,或者一个已声明且一个已继承)具有 相同的名称,但签名不是等效的,则 方法名称被认为是重载的。
这确实有可能。
答案 2 :(得分:0)
eat
中的方法Horse
不会覆盖Mammal
中的方法eat。这是因为参数不同。
eat方法是重载。
重载之间的选择发生在编译时,而不是运行时。它不是基于调用该方法的对象的实际类,而是基于编译时类型(如何声明变量)。