这种对超类和子类的访问限制背后的原因是什么?
What's the reason behind this access restriction for superclass and subclass?
我正在尝试理解我的代码的最后一条语句在 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()
是 "not defined in Rectangle." 尽管如此,我对这段代码的看法是:sameObjectDifferentType 是对既是 Rectangle 又是 ColoredRectangle 的对象的引用,因此我应该能够访问所有它的成员,无论我是将引用声明为 Rectangle 还是 ColoredRectangle。那么...为什么Java是这样设计的呢?
Rectangle sameObjectDifferentType = blueRectangle;
当您进行这样的声明时,您是在明确告诉编译器它应该被视为 Rectangle
。虽然在这种情况下它可能是 ColoredRectangle
,但该保证很快就会消失。
在这一行中,您声明 sameObjectDifferentType
属于 Rectangle
类型
Rectangle sameObjectDifferentType = blueRectangle;
在更多真实世界的示例中,这将允许您拥有几种不同的类型,您希望以相同的方式处理它们。 classic 示例是 CurrentAccount
、CheckingAccount
、SavingsAccount
,它们都继承自 Account
。
假设您的银行应用程序具有用于查找帐户并找出帐户持有人的代码。该代码将只处理抽象 Account
类型。这意味着将来当你引入一个 StudentAccount
时,如果它继承自 Account
你可以在你当前处理 Account
的所有地方使用一个 StudentAccount
而无需更改代码。
假设您的示例中有 FilledRectangle
和 WireFrameRegtangle
。你可以有一个适用于所有矩形的 calculateArea(Rectangle rect)
方法。
但是,为了获得这种能力和灵活性而做出的一个折衷是,当您将一个对象声明为超类时,您将失去直接处理子类class属性的能力class 类型,所以
sameObjectDifferentType.getColor(); //Won't compile
但是,Java 确实为您提供了一种返回子 class 的方法,正如您通过转换注意到的那样:
((ColoredRectangle) sameObjectDifferentType).getColor(); //Will compile
作为开发人员,您知道 sameObjectDifferentType
实际上是一个 ColoredRectangle
,所以您可以放心地 cast.However 如果您这样做了
((FilledRectangle) sameObjectDifferentType).getFillPattern();
你最终会得到 运行 次 ClassCastException
希望这对您有所帮助。
我正在尝试理解我的代码的最后一条语句在 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()
是 "not defined in Rectangle." 尽管如此,我对这段代码的看法是:sameObjectDifferentType 是对既是 Rectangle 又是 ColoredRectangle 的对象的引用,因此我应该能够访问所有它的成员,无论我是将引用声明为 Rectangle 还是 ColoredRectangle。那么...为什么Java是这样设计的呢?
Rectangle sameObjectDifferentType = blueRectangle;
当您进行这样的声明时,您是在明确告诉编译器它应该被视为 Rectangle
。虽然在这种情况下它可能是 ColoredRectangle
,但该保证很快就会消失。
在这一行中,您声明 sameObjectDifferentType
属于 Rectangle
Rectangle sameObjectDifferentType = blueRectangle;
在更多真实世界的示例中,这将允许您拥有几种不同的类型,您希望以相同的方式处理它们。 classic 示例是 CurrentAccount
、CheckingAccount
、SavingsAccount
,它们都继承自 Account
。
假设您的银行应用程序具有用于查找帐户并找出帐户持有人的代码。该代码将只处理抽象 Account
类型。这意味着将来当你引入一个 StudentAccount
时,如果它继承自 Account
你可以在你当前处理 Account
的所有地方使用一个 StudentAccount
而无需更改代码。
假设您的示例中有 FilledRectangle
和 WireFrameRegtangle
。你可以有一个适用于所有矩形的 calculateArea(Rectangle rect)
方法。
但是,为了获得这种能力和灵活性而做出的一个折衷是,当您将一个对象声明为超类时,您将失去直接处理子类class属性的能力class 类型,所以
sameObjectDifferentType.getColor(); //Won't compile
但是,Java 确实为您提供了一种返回子 class 的方法,正如您通过转换注意到的那样:
((ColoredRectangle) sameObjectDifferentType).getColor(); //Will compile
作为开发人员,您知道 sameObjectDifferentType
实际上是一个 ColoredRectangle
,所以您可以放心地 cast.However 如果您这样做了
((FilledRectangle) sameObjectDifferentType).getFillPattern();
你最终会得到 运行 次 ClassCastException
希望这对您有所帮助。