我很难理解有关覆盖和重载的一些原则。
public class Figure{
public void stampa(Figure f){
System.out.println("Figure");
}
}
public class Square extends Figure{
public void stampa(Square q){
System.out.println("Square");
}
}
public class Rectangle extends Square{
public void stampa(Rectangle r){
System.out.println("Rectangle");
}
public void stampa(Square r){
System.out.println("Particular Rectangle");
}
public void stampa(Figure f){
System.out.println("Particular Figure");
}
}
public class Test{
public static void main(String args[]){
Figure f1,f2;
Square q = new Rectangle();
Rectangle r = new Rectangle();
f1 = new Square();
f2 = new Rectangle();
f1.stampa(f2); //Figure
q.stampa(r); //Particular Rectangle
f1.stampa(q); //Figure
q.stampa(f1); //Particular Figure
q.stampa(q); //Particupar Rectangle
}
}
我知道public void stampa(Square q)
正在超载public void stampa(Figure f)
并且没有覆盖它。
public void stampa(Rectangle r)
和public void stampa(Figure f)
也在超载public void stampa(Square q)
。
Rectangle类中的public void stampa(Square q)
也会覆盖Square类中的方法。
第一个问题
关于这个结果:q.stampa(f1); //Particular Figure
我知道在编译时q
是Square
所以我会在public void stampa(Square q)
类中查看此方法Square
。并且在运行时q
是Rectangle
所以我认为结果可能是“特殊矩形”而不是“特殊图”
不确定我做错了什么
第二个问题
如果此时Rectangle
扩展Figure
而不再扩展Square
,我肯定会在Square q = new Rectangle();
上出现编译错误,变量q
会发生什么(会有Square q
这样的变量,或者我们没有名字q的任何变量?)以及q.stampa(f1);
感谢和抱歉我的英语,如果我在某些方面错了,请纠正我。
答案 0 :(得分:3)
第一个问题:
q
声明的类型是Square。 f1
声明的类型是图。因此,如果存在接受图(或图的超类)的方法,编译器会在类Square及其超类中查找名为stampa的方法。它找到了一个图:public void stampa(Figure f)
。在编译时,重要的是变量的声明类型。
现在,在运行时,将检查q
引用的对象的实际运行时类型:它是一个Rectangle。因此,运行时查找方法public void stampa(Figure f)
,它覆盖了Figure方法,在Rectangle中,以及它的所有超类,直到图。这是什么允许多态性。它在Rectangle中找到一个:
public void stampa(Figure f) {
System.out.println("Particular Figure");
}
第二个问题:
你确实会有一个编译错误,所以关于变量q的类型的推理没有意义:没有这样的变量,因为代码不能编译,因此类不是由编译器。
答案 1 :(得分:3)
我知道在编译时
q
是Square
所以我会在Square类中查看此方法public void stampa(Square q)
。
您忘记Square
包含两个方法:stampa(Square q)
和stampa(Figure f)
。后者继承自Figure
,在编译时被选为 most 唯一适当的重载。
并且在运行时
q
是Rectangle所以我认为结果可能是“特殊矩形”而不是“特殊图形”
在编译时选择重载,并在运行时覆盖。如上所述,stampa(Figure f)
已在编译时选中。实际调用后,运行时会看到q
是Rectangle
的实例,并将调用委托给Rectangle.stampa(Figure f)
。
至于第二个问题,我真的不明白你在问什么。编译错误意味着代码无效且没有任何反应。永远不会调用q.stampa(f1)
,永远不会返回结果。