简体   繁体   中英

What's the reason behind this access restriction for superclass and subclass?

I'm trying to understand the rationale for the last statement of my code being illegal in Java. See comment below.

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 
  }
}

I know that I shouldn't use this design, and instead use different constructors. I know that getColor() is "not defined in Rectangle." Still, the way I think about this code is: sameObjectDifferentType is a reference to an object that is both a Rectangle and a ColoredRectangle, and therefore I should be able to access all of its members regardless if I declare the reference as Rectangle or ColoredRectangle. So... why is Java designed like this?

Rectangle sameObjectDifferentType = blueRectangle;

When you make a declaration like this, you are explicitly telling the compiler that it should be treated as a Rectangle . While it may be a ColoredRectangle in this case, it would not take much for that guarantee to disappear.

In this line, you are declaring that sameObjectDifferentType is of a type Rectangle

Rectangle sameObjectDifferentType = blueRectangle;

In more real world examples, this would allow you to have several different types, that you would want to treat in the same way. The classic example is CurrentAccount , CheckingAccount , SavingsAccount which all inherit from Account .

Suppose your banking application had code to lookup an account and find out the account holder. That code would just deal with the abstract Account types. It means that in the future when you introduce a StudentAccount , providing it inherits from Account you can use a StudentAccount in all the places you currently deal with Account s without changing code.

Suppose you had a FilledRectangle and WireFrameRegtangle in your example. You could have a calculateArea(Rectangle rect) method that would apply to all Rectangles.

However, one trade off you make for this power and flexibility is that you lose the ability to directly deal with properties of the subclass when you declare an object to be of a super class type, so

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

However, Java does give you a way to get back to the subclass as you have noted by casting:

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

You as a developer know that sameObjectDifferentType is really a ColoredRectangle under the hood so you are safe to make this cast.However if you did

((FilledRectangle) sameObjectDifferentType).getFillPattern(); 

You would end up with a run time ClassCastException

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM