我目前正在阅读Java Book,并且我已经开始阅读有关继承和多态的内容。
我正在制作一个存储动物信息的测试程序,我想重载设置动物大小的方法。用户知道狗的大小,但没有其他动物,因此如果它不是狗,则将动物大小设置为0,对于狗,它使用自己的setSize方法和参数。
然而,我已经尝试了两种创建狗的方法,通过创建动物对象以及创建狗对象。我假设即使testDog1变量是Animal类型,它仍然可以从Dog类重载方法,因为它是一个狗对象。
有人可以解释为什么testDog1不起作用但testDog2有效吗?
public class Loader {
public static void main(String[] args){
int dogSize = 100;
Animal testDog1 = new Dog();
testDog1.setSize(dogSize);
Dog testDog2 = new Dog();
testDog2.setSize(dogSize);
}
}
public class Animal {
public int size;
public void setSize(){
size = 0;
System.out.println(size);
}
}
public class Dog extends Animal {
public void setSize(int dogSize){
size = dogSize;
System.out.println(size);
}
}
答案 0 :(得分:1)
如果要在代码中引用testDog1
,编译器会将其视为类Animal
。这意味着您可以使用Cat
或Bird
或其他任何其他setSize(int)
不存在的实例重新分配它。
testDog1
声明类型为Animal
后,您需要遵守该类合同。
目前为Dog
这一事实并不能使Dog
的具体方法可见。不过,您可能会在本书的下一章中学习如何进行投射。
答案 1 :(得分:1)
Animal testDog1 = new Dog();
只有在运行程序时,才会创建Dog的实例并将其分配给testDog1变量。即。)运行时。
编译器不运行程序或在检查正确性时对每个语句或变量的性质做出硬性和快速的假设。如果是这种情况,下面的stmt也会是编译时错误。
Animal testDog = null;
testDog.setSize(); // How can you call setSize() on null right? for the same reason mentioned above.
答案 2 :(得分:0)
在编译时,编译器知道的是testDog1
中您将引用Animal
。由于Animal
没有setSize(int)
,编译器无法找到它并且失败。
了解哪些操作在编译时完成(编译器知道变量的类型)以及哪一个在运行时完成(运行时知道对象的实际实例)非常重要。
答案 3 :(得分:0)
您的testDog1
在setSize(int dogSize)
类中找不到Animal
方法因此它是编译错误。
在testDog2
类中setSize(int dogSize)
找到Dog
方法的位置,它将被编译。
答案 4 :(得分:0)
testDog1是一个Animal
对象。如果不将其转换为Dog
,则不知道setSize(int)
存在。
(Dog)testDog1.setSize(dogSize)
告诉编译器它实际上是一只狗。