对超类和子类进行此访问限制的背后原因是什么?

时间:2019-01-12 16:36:32

标签: java inheritance subclass superclass

我试图理解我的代码的最后一条声明在Java中是非法的理由。请参阅下面的评论。

public class Rectangle {

private int height;
private int width;

public Rectangle(int height, int width) {
    this.height = height;
    this.width = width;
  }

}

class ColoredRectangle extends Rectangle {
private String color;

public ColoredRectangle(int height, int width, String color) {
    super(height, width);
    this.color = color;
}

public String getColor() {
    return color;
}

public static void main(String[] args) {
    ColoredRectangle blueRectangle = new ColoredRectangle(2, 4, "blue");
    Rectangle sameObjectDifferentType = blueRectangle;
    ((ColoredRectangle) sameObjectDifferentType).getColor(); //Will compile
    sameObjectDifferentType.getColor();  //Won't compile 
  }
}

我知道我不应该使用这种设计,而应该使用其他构造函数。我知道getColor()是“未在矩形中定义的”。尽管如此,我对这段代码的看法仍然是:sameObjectDifferentType是对同时为Rectangle和ColoredRectangle的对象的引用,因此无论我将引用声明为Rectangle还是ColoredRectangle,我都应该能够访问其所有成员。那么……为什么Java是这样设计的?

2 个答案:

答案 0 :(得分:0)

fetchForums

进行这样的声明时,您明确地告诉编译器应将其视为Rectangle sameObjectDifferentType = blueRectangle; 。尽管在这种情况下它可能是Rectangle,但这种保证消失并不会花费太多。

答案 1 :(得分:0)

在此行中,您声明sameObjectDifferentType的类型为Rectangle

Rectangle sameObjectDifferentType = blueRectangle;

在更多真实的示例中,这将允许您具有几种不同的类型,并且希望以相同的方式进行处理。经典示例是CurrentAccountCheckingAccountSavingsAccount,它们都是从Account继承的。

假设您的银行业务应用程序具有用于查找帐户并找出帐户持有人的代码。该代码将只处理抽象的Account类型。这意味着将来您引入StudentAccount时,只要它继承自Account,您就可以在当前处理StudentAccount的所有地方使用Account而无需更改代码。

假设您的示例中有一个FilledRectangleWireFrameRegtangle。您可能有一个适用于所有矩形的calculateArea(Rectangle rect)方法。

但是,要权衡这种功能和灵活性,您需要权衡的一点是,当您声明一个对象为超类类型时,您将无法直接处理子类的属性,因此

sameObjectDifferentType.getColor();  //Won't compile 

但是,Java确实为您提供了一种通过强制转换返回子类的方法:

((ColoredRectangle) sameObjectDifferentType).getColor(); //Will compile

作为开发人员,您知道sameObjectDifferentType实际上是ColoredRectangle的幕后黑手,因此您可以安全地进行此投射。但是,如果这样做了

((FilledRectangle) sameObjectDifferentType).getFillPattern(); 

您最终将获得运行时ClassCastException

希望这会有所帮助。