由于我是Java和OOP的新手,这对我来说很有用。假设我有一个类Animal
,以及扩展Animal的子类Dog
,Frog
,Cat
。 Animal
及其所有子类都有move()
方法。除了自己的代码之外,子类中的move()
在其中使用super.move()
。我的Main
类有一个变量currentAnimal
,它基本上保存了房间中当前动物的实例,因此一次只能存在1只动物(可以是Dog,Frog或Cat类)。
我将currentAnimal初始化为Animal currentAnimal = null
(使它成为Animal
类可能是错误的,因为它永远不会是Animal
类,而是一些子动物类(Frog,Dog,Cat) ),但我没有看到更好的选择,键入Object
而不是Animal
似乎不起作用)。程序运行时,它接受来自用户的命令,例如,如果命令为"new Dog"
,则执行以下Main.currentAnimal = new Dog()
。
然后我希望用户能够调用“move”命令,该命令将执行当前存储在move()
中的对象的currentAnimal
。问题发生在这里,因为编译器认为currentAnimal是Animal类的实例,它告诉我Animal
类具有move()
方法但具有不同的签名且无法编译。但我不希望它调用Animal.move()
,而是希望它调用move()
中当前对象的currentAnimal
(例如,如果对象属于Dog类,那么它将使用{{} 1}},而不是Dog.move()
)。如果我知道当前存储在currentAnimal中的哪个动物我将使用强制转换,但我不知道,我只知道currentAnimal中的动物有Animal.move()
方法,我想调用它。我该怎么做?
主要课程:
move()
动物类:
public class Main {
static Animal currentAnimal = null;
public static void main(String[] args) {
currentAnimal = new Dog(2,3);
currentAnimal.move("asd");
}
}
狗班:
public class Animal {
public void move(String s1, String s2){
System.out.println("animal.move - parameters: " + s1 + " " + s2);
}
}
它最终运行Animal.move()而不是Dog.move()。我不能用新的Dog()声明一个变量,因为它的变化取决于用户在执行期间给出的命令。只要没有动物,currentAnimal就为空
答案 0 :(得分:0)
如果你声明一个这样的变量:
Animal animal = new Dog();
animal.move();
由于java polymorphism principle,它将从move()
类执行Dog
方法。
但是,您获得的错误是由于子类中.move()
方法的覆盖(签名)不正确,与超类.move()
中的Animal
方法有关。< / p>
来自move()
的{{1}}方法具有签名:
Animal
public void move(String s1, String s2)
中的一个是:
Dog
那不是覆盖,而是重载(=相同的方法名称,但是参数不同,所以实际上只是一种不同的方法)。多态性仅适用于重写的方法。
要从超类覆盖方法,方法必须
public void move(String s1);
),这样就可以了void
)所以在public
中,向Dog
方法添加一个String参数,这样它需要两个字符串,或者在move()
move方法中删除一个String参数,然后你得到了预期的行为。
注意:在Animal
上添加注释@Override是一种很好的做法,因此当您对覆盖(继承)原则产生错误时,IDE会立即告诉您:
Dog.move()
基于您的评论的替代解决方案:如果您仍需要Animal上的move(String,String),但所有子动物都有move(String)方法,您可以向Animal添加一个抽象方法。 :
//in Dog
@Override
public void move(String s1, String s2) {
super.move("s1", "s2")
(...)
}
子类:
public abstract class Animal {
//protected because this will only be called from sub classes
protected void move(String st1, String st2) {
//implementation of method
}
//overload of the other move method (not override)
public abstract void move(String str); //no implementation
}
主要方法:
public class Dog extends Animal {
//mandatory override as this defined on the Animal level as abstract
@Override
public void move(String str) {
this.move("st1", "st2"); //call overloaded move defined on Animal level
//the rest of the implementation
}
}