Наследование и правила видимости. Зарезервированное слово super
В данном параграфе рассматривается ряд нетривиальных ситуаций, связанных с правилами видимости при наследовании.
Поля и методы, помеченные как private (“закрытый, частный”) наследуются, но в классах-наследниках недоступны. Это сделано в целях обеспечения безопасности. Пусть, например, некий класс Password1 обеспечивает проверку правильности пароля, и у него имеется строковое поле password (“пароль”), в котором держится пароль и с которым сравнивается введённый пользователем пароль. Если оно имеет тип public, такое поле общедоступно, и сохранить его в тайне мы не сможем. При отсутствии модификатора видимости или модификаторе protected на первый взгляд имеется необходимое ограничение доступа. Но если мы напишем класс Password2, являющийся наследником от Password1, в нём легко написать метод, “вскрывающий” пароль:
public String getPass(){
return password;
};
Если же поставить модификатор private, то в потомке до прародительского поля password не добраться!
То, что private-поля наследуются, проверить достаточно просто: зададим класс
public class TestPrivate1 {
private String s=”Значение поля private”;
public String get_s(){
return s;
}
}
и его потомок, который просто имеет другое имя, но больше ничего не делает:
public class TestPrivate2 extends TestPrivate1 {
}
Если из объекта, являющегося экземпляром TestPrivate2, вызвать метод get_s(), мы получим строку =”Значение поля private”:
TestPrivate2 tst=new TestPrivate2();
System.out.println(tst.get_s());
Таким образом, поле s наследуется. Но если в классе, где оно задано, не предусмотрен доступ к нему с помощью каких-либо методов, доступных в наследнике, извлечь информацию из этого поля оказывается невозможным.
Модификатор protected предназначен для использования соответствующих полей и методов разработчиками классов-наследников. Он даёт несколько большую открытость, чем пакетный вид доступа (по умолчанию, без модификатора), поскольку в дополнении к видимости из текущего пакета позволяет обеспечить доступ к таким членам в классах-наследниках, находящихся в других пакетах. Модификатором protected полезно помечать различного рода служебные методы, ненужные пользователям класса, но необходимые для функциональности этого класса.
Существует “правило хорошего тона”: поля данных принято помечать модификатором private, а доступ к этим полям обеспечивать с помощью методов с тем же именем, но префиксом get (“получить” - доступ по чтению) и set (“установить” - доступ по записи). Эти методы называют “геттерами” и “сеттерами”. Такие правила основаны на том, что прямой доступ по записи к полям данных может разрушить целостность объекта.
Рассмотрим следующий пример: пусть у нас имеется фигура, отрисовываемая на экране. Изменение её координат должно сопровождаться отрисовкой на новом месте. Но если мы напрямую изменили поле x или y, фигура останется на прежнем месте, хотя поля имеют новые значения! Если же доступ к полю осуществляется через методы setX и setY, кроме изменения значений полей будут вызваны необходимые методы, обеспечивающие перерисовку фигуры в новом месте. Также можно обеспечить проверку вводимых значений на допустимость.
Возможен и гораздо худший случай доступа к полям напрямую: пусть у нас имеется объект-прямоугольник, у которого заданы поля x1,y1- координаты левого верхнего угла,x2,y2- координаты правого нижнего угла,w - ширина, h – высота, s- площадь прямоугольника. Они не являются независимыми: w=x2-x1, h=y2-y1, s=w*h. Поэтому изменение какого-либо из этих полей должно приводить к изменению других. Если же, скажем, изменить только x2, без изменения w и s, части объекта станут несогласованными. Предсказать, как поведёт себя в таких случаях программа, окажется невозможно!
Ещё хуже обстоит дело при наличии наследования в тех случаях, когда в потомке задано поле с тем же именем, что и в прародителе, имеющее совместимый с прародительским полем тип. Так как для полей данных полиморфизм не работает, возможны очень неприятные ошибки.
Указанные выше правила хорошего тона программирования нашли выражение в среде NetBeans при установленном пакете NetBeans Enterprise Pack. В ней при разработке UML-диаграмм добавление в класс поля автоматически приводит к установке ему модификатора private и созданию двух public-методов с тем же именем, но префиксами get и set. Эти типы видимости в дальнейшем, конечно, можно менять, как и удалять ненужные методы.
Иногда возникает необходимость вызвать поле или метод из прародительского класса. Обычно это бывает в случаях, когда в классе-потомке задано поле с таким же именем (но, обычно, другим типом) или переопределён метод. В результате видимость прародительского поля данных или метода в классе-потомке утеряна. Иногда говорят, что поле или метод затеняются в потомке. В этих случаях используют вызов super.имяПоля или super.имяМетода(список параметров). Слово super в этих случаях означает сокращение от superclass. Если метод или поле заданы не в непосредственном прародителе, а унаследованы от более далёкого прародителя, соответствующие вызовы всё равно будут работать. Но комбинации вида super.super.имя не разрешены.
Использовать вызовы с помощью слова super разрешается только для методов и полей данных объектов. Для методов и переменных класса (то есть объявленных с модификатором static) вызовы с помощью ссылки super запрещены.
- Содержание
- Глава 1. Общие представления о языке Java 6
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans 26
- Глава 3. Примитивные типы данных и операторы для работы с ними 78
- Глава 4. Работа с числами в языке Java 95
- Глава 5. Управляющие конструкции 112
- Глава 6. Начальные сведения об объектном программировании 128
- Глава 7. Важнейшие объектные типы 175
- Введение
- Глава 1. Общие представления о языке Java
- 1.1. Java и другие языки программирования. Системное и прикладное программирование
- 1.2. Виртуальная Java-машина, байт-код, jit-компиляция. Категории программ, написанных на языке Java
- 1.3.Алфавит языка Java. Десятичные и шестнадцатеричные цифры и целые числа. Зарезервированные слова Алфавит языка Java
- Десятичные и шестнадцатеричные цифры и целые числа
- Зарезервированные слова языка Java
- 1.4. Управляющие последовательности. Символы Unicode. Специальные символы Управляющие последовательности
- Простые специальные символы
- Составные специальные символы
- 1.5.Идентификаторы. Переменные и типы. Примитивные и ссылочные типы
- Краткие итоги по главе 1
- Задания
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans
- 2.1.Процедурное и объектно-ориентированное программирование. Инкапсуляция
- 2.2. Работа со ссылочными переменными. Сборка мусора
- 2.3. Проекты NetBeans. Пакеты. Уровни видимости классов. Импорт классов
- 2.4. Базовые пакеты и классы Java
- 2.5. Создание в NetBeans простейшего приложения Java
- 2.6. Компиляция файлов проекта и запуск приложения
- 2.7. Структура проекта NetBeans
- 2.8. Создание в NetBeans приложения Java с графическим интерфейсом
- 2.9. Редактор экранных форм
- 2.10. Внешний вид приложения
- 2.11. Ведение проектов
- 2.11. Редактирование меню экранной формы
- 2.12. Создание нового класса
- 2.13. Документирование исходного кода в Java
- 2.14. Основные компоненты пакетов swing и awt
- 2.15. Технологии Java и .Net
- Краткие итоги по главе 2
- Задания
- Глава 3. Примитивные типы данных и операторы для работы с ними
- 3.1.Булевский (логический) тип
- 3.2.Целые типы, переменные, константы
- 3.3.Основные операторы для работы с целочисленными величинами
- 3.4.Вещественные типы и класс Math
- 3.5.Правила явного и автоматического преобразования типа при работе с числовыми величинами
- 3.6. Оболочечные классы. Упаковка (boxing) и распаковка (unboxing)
- 3.7.Приоритет операторов
- 3.8.Типы-перечисления (enum)
- Краткие итоги по главе 3
- Задания
- Глава 4. Работа с числами в языке Java
- 4.1 Двоичное представление целых чисел Позиционные и непозиционные системы счисления
- Двоичное представление положительных целых чисел
- Двоичное представление отрицательных целых чисел. Дополнительный код
- Проблемы целочисленной машинной арифметики
- Шестнадцатеричное представление целых чисел и перевод из одной системы счисления в другую
- 4.2. Побитовые маски и сдвиги
- 4.3. Двоичное представление вещественных чисел Двоичные дроби
- Мантисса и порядок числа
- Стандарт ieee 754 представления чисел в формате с плавающей точкой*
- Краткие итоги по главе 4
- Задания
- Глава 5. Управляющие конструкции Составной оператор
- Условный оператор if
- Оператор выбора switch
- Условное выражение …?... : …
- Оператор цикла for
- Оператор цикла while – цикл с предусловием
- Оператор цикла do...While – цикл с постусловием
- Операторы прерывания continue, break, return, System.Exit
- Краткие итоги по главе 5
- Задания
- Глава 6. Начальные сведения об объектном программировании
- Наследование и полиморфизм. Uml-диаграммы
- Функции. Модификаторы. Передача примитивных типов в функции
- Локальные и глобальные переменные. Модификаторы доступа и правила видимости. Ссылка this
- Передача ссылочных типов в функции. Проблема изменения ссылки внутри подпрограммы
- Наследование. Суперклассы и подклассы. Переопределение методов
- Наследование и правила видимости. Зарезервированное слово super
- Статическое и динамическое связывание методов. Полиморфизм
- Базовый класс Object
- Конструкторы. Зарезервированные слова super и this. Блоки инициализации
- Удаление неиспользуемых объектов и метод finalize. Проблема деструкторов для сложно устроенных объектов
- Перегрузка методов
- Правила совместимости ссылочных типов как основа использования полиморфного кода. Приведение и проверка типов
- Рефакторинг
- Reverse engineering – построение uml-диаграмм по разработанным классам
- Краткие итоги по главе 6
- Задания
- Глава 7. Важнейшие объектные типы Массивы
- Коллекции, списки, итераторы
- Работа со строками в Java. Строки как объекты. Классы String, StringBuffer и StringBuilder
- Работа с графикой
- Исключительные ситуации Обработка исключительных ситуаций
- Иерархия исключительных ситуаций
- Объявление типа исключительной ситуации и оператор throw
- Объявление метода, который может возбуждать исключительную ситуацию. Зарезервированное слово throws
- Работа с файлами и папками
- Краткие итоги по главе 7
- Задания
- Глава 8. Наследование: проблемы и альтернативы. Интерфейсы. Композиция Проблемы множественного наследования классов. Интерфейсы
- Отличия интерфейсов от классов. Проблемы наследования интерфейсов
- Пример на использование интерфейсов
- Композиция как альтернатива множественному наследованию
- Краткие итоги по главе 8
- Задания
- Глава 9. Дополнительные элементы объектного программирования на языке Java Потоки выполнения (threads) и синхронизация
- Преимущества и проблемы при работе с потоками выполнения
- Синхронизация по ресурсам и событиям
- Класс Thread и интерфейс Runnable. Создание и запуск потока выполнения
- Поля и методы, заданные в классе Thread
- Подключение внешних библиотек dll.“Родные” (native) методы*
- Краткие итоги по главе 9
- Задания
- Глава 10. Введение в сетевое программирование Краткая справка по языку html
- Апплеты
- Сервлеты
- Технология jsp – Java Server Pages
- Краткие итоги по главе 10
- Задания
- Глава 11. Встроенные классы Виды встроенных классов
- Вложенные (nested) классы и интерфейсы
- Внутренние (inner) классы
- Локальные (local) классы
- Анонимные (anonimous) классы и обработчики событий
- Анонимные (anonimous) классы и слушатели событий (listeners)
- Краткие итоги по главе 11
- Задания
- Глава 12. Компонентное программирование Компонентная архитектура JavaBeans
- Мастер создания компонента в NetBeans
- Пример создания компонента в NetBeans – панель с заголовком
- Добавление в компонент новых свойств
- Добавление в компонент новых событий
- Краткие итоги по главе 12
- Задания
- Литература
- Дополнительная литература
- 276 Курс подготовлен при поддержке Sun Microsystems