Хотя подкласс включает все элементы (члены) своего суперкласса, он не может обращаться к тем элементам суперкласса, которые были объявлены как private. Например, рассмотрим следующую простую иерархию классов:
/* В иерархии классов private члены остаются private для ее классов.
Эта программа содержит ошибку и не будет компилироваться. */
// Создать суперкласс.
class A {
int i; // public по умолчанию
private int j; // private для A
void setij(int x, int y) {
i = x;
j = y;
}
}
// j класса A здесь не доступна.
class B extends A {
int total;
void sum() {
total = i + j; // ОШИБКА, j здесь не доступна
}
}
class Access {
public static void main(String args[]) {
B subOb = new B();
subOb.setij(10, 12);
subOb.sum();
System.out.println("Всего " + subOb.total);
}
}
Эта программа не будет компилироваться, потому что ссылка на j внутри метода sum() класса в вызывает нарушение правил доступа. С тех пор как j объявлена с помощью private, она доступна только другим членам его собственного класса. Подклассы не имеют доступа к ней.
Замечание. Член класса, который был объявлен как private, остается private для этого класса. Он не доступен любым кодам вне его класса, включая подклассы.
Практический пример
Рассмотрим практический пример, который поможет проиллюстрировать мощь наследования. Последняя версия класса Box, будет расширена, чтобы включить четвертый компонент с именем weight. Таким образом, новый класс будет содержать ширину, высоту, глубину и вес блока.
// Программа использует наследование для расширения Box.
class Box {
double width;
double height;
double depth;
// создать клон объекта
Box(Box ob) { // передать объект конструктору
width = ob.width;
height = ob.height;
depth = ob.depth;
}
// конструктор, используемый, когда указаны все размеры
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// конструктор, используемый, когда размеры не указаны
Box() {
width = -1; // использовать -1 для указания
height = -1; // неинициализированного
depth = -1; // блока
}
// конструктор, используемый для создания куба
Box(double len) {
width = height = depth = len;
}
// вычислить и вернуть объем
double volume() {
return width * height * depth;
}
}
// Box расширяется для включения веса.
class BoxWeight extends Box {
double weight; // вес блока
// конструктор для BoxWeight
BoxWeight(double w, double h, double d, double m) {
width = w;
height = h;
depth = d;
weight = m;
}
}
class DemoBoxWeight {
public static void main(String args[]) {
BoxWeight myboxl = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight( 2, 3, 4, 0.076);
BoxWeight наследует все характеристики Box и прибавляет к ним компонент weight. Для BoxWeight нет необходимости заново создавать все свойства Box. Можно просто расширить Bох, чтобы достичь своих собственных целей.
Главное преимущество наследования состоит в том, что, как только вы создали суперкласс, который определяет общие для набора объектов атрибуты, его можно использовать для создания любого числа более специфичных подклассов. Каждый подкласс может добавить свою собственную классификацию. Например, следующий класс наследует Box и прибавляет цветовой атрибут:
// Box расширяется для включения цвета.
class ColorBox extends Box {
int color; // color of box
ColorBox(double w, double h, double d, int c) {
width = w;
height = h;
depth = d;
color = c;
}
}
Помните, как только вы создали суперкласс, который определяет общие аспекты объекта, этот суперкласс может наследоваться для формирования специализированных классов. Каждый подкласс просто прибавляет свои собственные, уникальные атрибуты. В этом сущность наследования.