1

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

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)

同样public void stampa(Square q)在 Rectangle 类中覆盖 Square 类中的方法。

第一个问题

这是关于这个结果的:q.stampa(f1); //Particular Figure 我知道在编译时q是一个,所以我会在课堂Square上看看这个方法。在运行时,我认为结果可能是“特定矩形”而不是“特定图形”public void stampa(Square q)SquareqRectangle

不知道我做错了什么

第二个问题

如果此时Rectangle扩展Figure而不是更多Square,我肯定会对Square q = new Rectangle();变量发生的事情有编译错误q(会有这样的变量,Square q或者我们没有任何名称为 q 的变量?),结果会是什么q.stampa(f1);

感谢并为我的英语感到抱歉,如果我在某些时候错了,请纠正我。

4

2 回答 2

4

第一个问题:

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

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

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

第二个问题:

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

于 2017-01-13T21:08:19.920 回答
3

我知道在编译时q是一个,所以我将在 Square 类中Square查看这个方法。public void stampa(Square q)

您忘记了Square包含两种方法:stampa(Square q)stampa(Figure f). 后者继承自Figure并在编译时选择为合适的重载。

在运行时q是矩形,所以我认为结果可能是“特定矩形”而不是“特定图形”

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

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

于 2017-01-13T21:12:19.790 回答