Java 重载和覆盖的方法选择

Java method selection with overloading and overriding

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

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)

此外,矩形 class 中的 public void stampa(Square q) 覆盖了方形 class 中的方法。

第一题

关于这个结果:q.stampa(f1); //Particular Figure 我知道在编译时 q 是一个 Square,所以我将在 Square class 中查看此方法 public void stampa(Square q)。在 运行 时间 qRectangle 所以我认为结果可能是 "Particular Rectangle" 而不是 "Particular Figure"

不确定我做错了什么

第二题

如果此时 Rectangle 扩展 Figure 而不再扩展 Square,我肯定会在 Square q = new Rectangle(); 上出现编译错误 [=19] =](将有一个变量 Square q 或者我们没有任何名称为 q 的变量?) q.stampa(f1);

的结果是什么

谢谢,对不起我的英语,如果我在某些时候错了,请纠正我。

第一个问题:

q 声明的类型是 Square。 f1 的声明类型是 Figure。因此编译器在 class Square 及其 superclasses 中查找名为 stampa 的方法,如果存在接受 Figure(或 Figure 的 superclass)的方法。它在图中找到一个:public void stampa(Figure f)。在编译时,重要的是变量的声明类型。

现在,在运行时,检查 q 引用的对象的实际运行时类型:它是一个矩形。因此,运行时会在 Rectangle 中寻找覆盖 Figure 方法的方法 public void stampa(Figure f),以及 Figure 之前的所有超classes。这就是允许多态性的原因。它在矩形中找到一个:

public void stampa(Figure f) {
    System.out.println("Particular Figure");
}

第二个问题:

您确实会遇到编译错误,因此对变量 q 的类型进行推理没有意义:不会有这样的变量,因为代码无法编译,而 class 是因此不是由编译器生成的。

I know that at compile-time q is an Square so i will look at this method public void stampa(Square q)in Square class.

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

and at run-time q is Rectangle so i thought the result might be "Particular Rectangle" instead of "Particular Figure"

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

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