具有重载和覆盖的Java方法选择

时间:2017-01-13 20:53:04

标签: java overloading override dynamic-binding static-binding

我很难理解有关覆盖和重载的一些原则。

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 我知道在编译时qSquare所以我会在public void stampa(Square q)类中查看此方法Square。并且在运行时qRectangle所以我认为结果可能是“特殊矩形”而不是“特殊图”

不确定我做错了什么

第二个问题

如果此时Rectangle扩展Figure而不再扩展Square,我肯定会在Square q = new Rectangle();上出现编译错误,变量q会发生什么(会有Square q这样的变量,或者我们没有名字q的任何变量?)以及q.stampa(f1);

的结果是什么?

感谢和抱歉我的英语,如果我在某些方面错了,请纠正我。

2 个答案:

答案 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)

  

我知道在编译时qSquare所以我会在Square类中查看此方法public void stampa(Square q)

您忘记Square包含两个方法:stampa(Square q)stampa(Figure f)。后者继承自Figure,在编译时被选为 most 唯一适当的重载。

  

并且在运行时q是Rectangle所以我认为结果可能是“特殊矩形”而不是“特殊图形”

在编译时选择重载,并在运行时覆盖。如上所述,stampa(Figure f)已在编译时选中。实际调用后,运行时会看到qRectangle的实例,并将调用委托给Rectangle.stampa(Figure f)

至于第二个问题,我真的不明白你在问什么。编译错误意味着代码无效且没有任何反应。永远不会调用q.stampa(f1),永远不会返回结果。