Задача третьего этапа — уточнить отношения классов, определить их скрытые и интерфейсные части. Существенный недостаток нашего построения в том, что, фактически, ни какие из определенных классов не находятся в отношении наследования — базовый–производный, а это значит, что мы не получим одного из серьезных преимуществ ООПрограммирования — повторного использования кода. Продолжим процесс проектирования в этом направлении.
Приведем два приема, которые позволяют создавать новые абстракции, полезные в ООП. Первый из них состоит в выделении упорядоченных пар классов и постановке к каждой паре вопроса: “А почему ТВторойКласс не является ТПервыйКласс с некоторым дополнением?”. При ответе на этот вопрос необходимо опираться на опыт программирования.
Итак, почему TTalk не является TStringList с некоторым дополнением? Почти очевидно, что является. Доклад, это текст (TStringList) с заглавием, автором и датой “опубликования”. При определении TTalk на базе TStringList поле Text становится ненужным — доклад является производным классом от TStringList, а значит автоматически включает список строк! Кроме исчезновения поля, проще станет обращаться и к методам класса–предка, теперь это методы и нашего класса. Список строк является хорошей основой и для других классов данного проекта.
Второй прием абстрагирования состоит в выделении некоторого подмножества схожих классов и постановке вопроса: ”Что общего между этими понятиями?”. Предварительная проработка позволит нам не “тонуть в болоте теории схожести”, а взять за основу общности наличие однотипных полей и методов. Вот результат выделения общих полей и методов классов TTalk, TAnnouncement и TConf.
Вопрос выделения общих свойств не так прост. Даже в нашем случае мы сделали промежуточное обобщение. Для конференции автор — это автор аннотации, возможно он же и лидер дискуссии. Другие лидеры дискуссии могут быть указаны прямо в аннотации.
Мы назвали эту общую часть документом. Теперь наши классы могут быть объявлены следующим образом:
Разве это не здорово? Мы стали понимать свою задачу с точки зрения работы с новым понятием — документом. Выяснилось, что имеется всего три типа документов, и они очень мало отличаются друг от друга.
Среди недостатков нового проекта следует отметить поле FileName в документах разного типа. Характерной чертой этих документов является то, что их содержание определяется целым файлом, в то время как содержание TTalk определяется частью файла. Устраним этот недостаток, введя новый тип:
Новое понятие полностью исчерпывает особенности TAnnouncement, а описание TConf снова упрощается. На этом первая попытка выяснения отношений классов успешно завершена.
Обратимся теперь к вопросу скрытия полей и выяснению типов методов наших классов. Хотя многие распространенные языки программирования позволяют не скрывать (не инкапсулировать) данные объектов, в Delphi Object Pascal для этого практически нет оснований. Все поля данных должны быть сделаны свойствами. Некоторые свойства могут быть доступны только для чтения, другие для модификации, а третьи и для чтения и для модификации.
К свойствам доступным только для чтения очевидно относится свойство Stored. Устанавливать признак должны методы класса, а вне класса достаточно лишь знать записан документ или нет. К свойствам доступным только для модификации можно отнести Offset. Действительно, зачем знать эту величину вне объекта? К свойствам доступным для записи и чтения относятся Caption, Date, Author, FileName.
Теперь остановимся на методах. Очевидно методы работы со свойствами Caption, Date, Author, FileName одинаковы для всех классов и их можно сделать статическими. А вот LoadHdr, LoadBody и Store будут существенно различаться. Поскольку мы будем работать со списками, в которых хранятся указатели на объекты разных типов, следует сделать эти методы виртуальными. По этой же причине виртуальными должны быть и деструкторы классов.
Метод Store для абстрактного класса TDoc лучше сделать protected — видимым для потомков, но не видимым для пользователей. Приведем результат проектирования.
Обратите внимание, как свойство Stored перенесено из protected в public, мы опустили все его спецификации.
Описания несколько усложнились. Это произошло по двум причинам. Во–первых мы защитили наши объекты от нежелательного вмешательства, скрыв данные и показав доступные свойства. Вторая причина в том, что нам пришлось указать явно перекрытие виртуальных методов. В действительности выгоды кодирования еще впереди.
Опубликовал Kest
October 12 2011 13:29:43 ·
0 Комментариев ·
5103 Прочтений ·
• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •
Комментарии
Нет комментариев.
Добавить комментарий
Рейтинги
Рейтинг доступен только для пользователей.
Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.
Нет данных для оценки.
Гость
Вы не зарегистрированны? Нажмите здесь для регистрации.