Отношения между классами. Клиенты и наследники

Отношения между классами. Клиенты и наследники

Каждый класс , как не раз отмечалось, играет две роли: он является модулем - архитектурной единицей, и он имеет содержательный смысл, определяя некоторый тип данных . Но классы программной системы - это ансамбль, в котором классы, играя свои роли, не являются независимыми - все они находятся в определенных отношениях друг с другом. Два основных типа отношений между классами определены в ОО-системах. Первое отношение "клиенты и поставщики" , называется часто клиентским отношением или отношением вложенности (встраивания) . Второе отношение "родители и наследники" называется отношением наследования .

Определение 1. Классы А и В находятся в отношении " клиент-поставщик ", если одним из полей класса В является объект класса А . Класс А называется поставщиком класса В , класс В называется клиентом класса А .

Определение 2. Классы А и В находятся в отношении " родитель - наследник ", если при объявлении класса В класс А указан в качестве родительского класса. Класс А называется родителем класса В , класс В называется наследником класса А .

Оба отношения - наследования и вложенности - являются транзитивными. Если В - клиент А , а С - клиент В , то отсюда следует, что С - клиент А . Если В - наследник А , а С - наследник В , то отсюда следует, что С - наследник А .

Определения 1 и 2 задают прямых или непосредственных клиентов и поставщиков, прямых родителей и наследников. Вследствие транзитивности необходимо ввести понятие уровня. Прямые клиенты и поставщики, прямые родители и наследники относятся к соответствующему уровню 1 (клиенты уровня 1, поставщики уровня 1 и так далее). Затем следует рекурсивное определение : прямой клиент клиента уровня k относится к уровню k+1 .

Для отношения наследования используется терминология, заимствованная из естественного языка. Прямые классы-наследники часто называются сыновними или дочерними классами . Непрямые родители называются предками, а их непрямые наследники - потомками .

Замечу, что цепочки вложенности и наследования могут быть достаточно длинными. На практике вполне могут встречаться цепочки длины 10. Например, библиотечные классы, составляющие систему Microsoft Office, полностью построены на отношении вложенности . При программной работе с объектами Word можно начать с объекта, задающего приложение Word , и добраться до объекта, задающего отдельный символ в некотором слове некоторого предложения одного из открытых документов Word . Для выбора нужного объекта можно задать такую цепочку: приложение Word - коллекция документов - документ - область документа - коллекция абзацев - абзац - коллекция предложений - предложение - коллекция слов - слово - коллекция символов - символ. В этой цепочке каждому понятию соответствует класс библиотеки Microsoft Office, где каждая пара соседствующих классов связана отношением " поставщик-клиент ".

Классы библиотеки FCL связаны как отношением вложенности , так и отношением наследования . Длинные цепочки наследования достаточно характерны для классов этой библиотеки.

Отношения "является" и "имеет"

При проектировании классов часто возникает вопрос, какое же отношение между классами нужно построить. Рассмотрим совсем простой пример двух классов - Square и Rectangle , описывающих квадраты и прямоугольники. Наверное, понятно, что эти классы следует связать скорее отношением наследования , чем вложенности ; менее понятным остается вопрос, а какой из этих двух классов следует сделать родительским. Еще один пример двух классов - Car и Person , описывающих автомобиль и персону. Какими отношениями с этими классами должен быть связан класс Person_of_Car , описывающий владельца машины? Может ли он быть наследником обоих классов? Найти правильные ответы на эти вопросы проектирования классов помогает понимание того, что отношение " клиент-поставщик " задает отношение "имеет" ("has") , а отношение наследования задает отношение "является" ("is a") . В случае классов Square и Rectangle понятно, что каждый объект квадрат "является" прямоугольником, поэтому между этими классами имеет место отношение наследования , и родительским классом является класс Rectangle , а класс Square является его потомком .

В случае автомобилей, персон и владельцев авто также понятно, что владелец "имеет" автомобиль и "является" персоной. Поэтому класс Person_of_Car является клиентом класса Car и наследником класса Person .

Отношение вложенности

Рассмотрим два класса A и B , связанных отношением вложенности . Оба класса применяются для демонстрации идей и потому устроены просто, не неся особой смысловой нагрузки. Пусть класс-поставщик A уже построен. У класса два поля, конструктор, один статический и один динамический метод. Вот его текст:

Построим теперь класс B - клиента класса A . Класс будет устроен похожим образом, но в дополнение будет иметь одним из своих полей объект inner класса A :

Обратите внимание: конструктор клиента (класса B ) отвечает за инициализацию полей класса, поэтому он должен создать объект поставщика (класса A ), вызывая, как правило, конструктор поставщика. Если для создания объектов поставщика требуются аргументы, то они должны передаваться конструктору клиента, как это сделано в нашем примере.

📎📎📎📎📎📎📎📎📎📎