В чем причина такого ограничения доступа для суперкласса и подкласса? - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь понять причину, по которой последнее утверждение моего кода является недопустимым в 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 голосов
/ 12 января 2019

В этой строке вы заявляете, что sameObjectDifferentType имеет тип Rectangle

Rectangle sameObjectDifferentType = blueRectangle;

В более реальных примерах это позволит вам иметь несколько различных типов, которые вы хотели бы обрабатывать одинаково. Классический пример - CurrentAccount, CheckingAccount, SavingsAccount, которые все наследуются от Account.

Предположим, в вашем банковском приложении был код для поиска учетной записи и выяснения владельца учетной записи. Этот код будет иметь дело только с абстрактными типами Account. Это означает, что в будущем, когда вы введете StudentAccount, при условии, что он наследует от Account, вы можете использовать StudentAccount во всех местах, где вы в настоящее время имеете дело с Account s, без изменения кода.

Предположим, у вас есть FilledRectangle и WireFrameRegtangle в вашем примере. У вас может быть метод calculateArea(Rectangle rect), который будет применяться ко всем прямоугольникам.

Тем не менее, один компромисс, который вы делаете для этой мощи и гибкости, заключается в том, что вы теряете возможность напрямую работать со свойствами подкласса, когда объявляете объект типом суперкласса, поэтому

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

Тем не менее, Java дает вам возможность вернуться к подклассу, как вы заметили, приведя:

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

Вы, как разработчик, знаете, что sameObjectDifferentType - это на самом деле ColoredRectangle под капотом, так что вы можете сделать этот бросок. Однако, если вы сделали

((FilledRectangle) sameObjectDifferentType).getFillPattern(); 

В результате вы получите ClassCastException во время выполнения

Надеюсь, это поможет.

0 голосов
/ 12 января 2019
Rectangle sameObjectDifferentType = blueRectangle;

Когда вы делаете такое объявление, вы явно указываете компилятору, что его следует рассматривать как Rectangle. Хотя в этом случае это может быть ColoredRectangle, для того чтобы эта гарантия исчезла, не потребовалось бы много времени.

...