【问题标题】:What's the reason behind this access restriction for superclass and subclass?超类和子类的访问限制背后的原因是什么?
【发布时间】:2019-06-07 06:26:22
【问题描述】:

我试图了解我的代码的最后一条语句在 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 会这样设计?

【问题讨论】:

  • color = this.color 应该是this.color = color
  • 我知道 getColor() 是“未在 Rectangle 中定义的。” 这完全正确。 getColor() 未在 Rectangle 中定义。你一开始就想对了。
  • 如果你有另一个类是Rectangle 并且有一个getColor() 方法会发生什么?现在我们甚至不能输入检查这个表达式。
  • Java 会如何设计?这就是 OOP 的工作原理 - 并非所有 Rectangles 也是 ColoredRectangles。
  • Rectangle 的构造函数是倒退的,顺便说一句:它从成员变量更新其参数!

标签: java inheritance subclass superclass


【解决方案1】:

在这一行中,您声明sameObjectDifferentType 属于Rectangle 类型

Rectangle sameObjectDifferentType = blueRectangle;

在更真实的示例中,这将允许您拥有几种不同的类型,您希望以相同的方式对待它们。经典的例子是CurrentAccountCheckingAccountSavingsAccount,它们都继承自Account

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

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

但是,您为这种功能和灵活性所做的一个权衡是,当您将对象声明为超类类型时,您将失去直接处理子类属性的能力,因此

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

但是,Java 确实为您提供了一种返回子类的方法,正如您通过强制转换所指出的那样:

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

作为开发人员,您知道 sameObjectDifferentType 在幕后实际上是 ColoredRectangle,因此您可以安全地进行此演员阵容。但是,如果您这样做了

((FilledRectangle) sameObjectDifferentType).getFillPattern(); 

您最终会遇到运行时 ClassCastException

希望这会有所帮助。

【讨论】:

  • 谢谢@yinder,如果您满意,请点击旁边的勾号将我的答案标记为已接受?
【解决方案2】:
Rectangle sameObjectDifferentType = blueRectangle;

当你做出这样的声明时,你明确地告诉编译器它应该被视为Rectangle。虽然在这种情况下它可能是 ColoredRectangle,但该保证很快就会消失。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-16
    • 2017-12-04
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 2020-01-26
    相关资源
    最近更新 更多