Модификаторы доступа при наследовании
На 3-ем занятии мы рассматривали описатели ограничения доступа (или, более кратко, модификаторы доступа). Несколько моментов в этом рассмотрении остались за рамками наших возможностей. Теперь, после знакомства с наследованием классов, мы можем доопределить их смысл. Поля и методы классов могут быть описаны как
- public — означает, что данный элемент доступен без каких-либо ограничений;
- private — доступ разрешен только из данного класса;
- protected — доступ разрешен из данного класса и из всех классов-потомков
- без описателя — доступ разрешен из всех классов данного пакета
Т.е. public -поля и методы доступны без ограничений во всех классах; private доступны только в данном классе и недоступны в порожденных классах; protected отличаются от private тем, что доступны в порожденных классах, а поля и методы без описателя доступны только в классах данного пакета вне зависимости от наследования.
Наследование классов — инструмент построения абстракций
(Небольшое теоретическое отступление)
Вместе с другими категориями ООП (полиморфизм, инкапсуляция) наследование служит инструментом построения абстракций. Причем, приемы, применяемые в ООП, не совсем обычны для тех, кто ранее программировал без использования принципов ООП.
Рассмотрим, например, как выглядят возможности наследования с первого взгляда. Наследование дает возможность построить простой класс, потом на его базе более сложный (добавив поля и методы), потом еще более сложный и т.д. Так это выглядит на первый взгляд. Но это, можно сказать, примитивный взгляд на возможности механизма наследования.
В ООП наследование обычно используется иначе и для других целей. Наследование классов — это мощный аппарат построения абстракций. При создании иерархии наследования классов в вершине иерархии расположены наиболее абстрактные сущности, которые все более конкретизируются и специализируются при движении вниз по дереву классов.
Для более предметного обсуждения рассмотрим несколько типичных примеров построения дерева наследования в стиле ООП.
Примеры
Рисунок 1.
Замечание
В визуальном представлении дерева наследования его изображают сверху вниз - от базовых классов к производным. На основе такого представления формируется и терминология (например, upcasting и downcasting, см. ниже).
Тип "Птицы" включает в себя свойства, характерные для всех птиц. А порожденные от него типы "Вороны" и "Попугаи" добавляют (каждый) какие-то свойства, характерные только для данных видов птиц.
Тип "Печатное издание" хранит наиболее общую информацию, характерную для всех печатных изданий. Например, каждое печатное издание имеет наименование. В типах, порожденных от него, добавляются свойства, характерные только для книг (например — список авторов), журналов (год, номер) или газет (дата).
Приведенные примеры демонстрируют не усложнение, а детализацию и конкретизацию классов при наследовании. Именно это является основным общепринятым принципом при построении дерева наследования классов: наверху — наиболее общие, абстрактные понятия, и при движении вниз по дереву иерархии они детализируются.
Можно поставить такую абстрактную задачу.
Пусть требуется формировать множества, которые могут включать в себя как элементарные объекты, так и множества того же типа. Набор типов элементарных объектов фиксирован.
Правильное решение состоит в том, что в вершину иерархии мы помещаем класс для самого этого множества, а классы элементарных объектов мы строим как наследники класса множества. Детализация заключается в том, что эти классы — это множества из одного элемента.
В дальнейшем изучении мы постараемся помнить о том, что наследование — это механизм построения на основе более общих, более абстрактных классов новых классов — более специфических, более конкретных.
Продолжим знакомство с возможностями аппарата наследования классов.