Структурное наследование
Определение: структурное наследование Структурное наследование применяется, если A, отложенный класс, представляет общее структурное свойство, а B, который может быть отложенным или эффективным, представляет некоторый тип объектов, обладающих этим свойством. |
Обычно A представляет математическое свойство, которым может обладать некоторое множество объектов. Например, A может быть классом COMPARABLE, поставляемым с такими операциями, как infix "<" и infix ">=", представляющим объекты с заданным отношением полного порядка. Класс, которому необходимо отношение порядка, такой как STRING, становится наследником COMPARABLE.
Наследование таким способом от нескольких родителей является обычным приемом. Например, класс INTEGER в библиотеке Kernel наследует от COMPARABLE и класса NUMERIC (с такими компонентами, как infix "+" и infix "*"), задающего арифметические свойства. (Класс NUMERIC более точно представляет математическое понятие кольца.)
В чем разница между конкретизацией и структурным наследованием? При конкретизации B представляет то же понятие, что и A, отличаясь большей степенью реализации; при структурном наследовании B представляет собственную абстракцию, для которой A задает лишь один из аспектов, такой как порядок на объектах или наличие арифметических операций.
Валден и Нерсон заметили, что новички иногда верят, что они используют подобную форму наследования, подменяя фактически имеющее место отношение "is" вариантом схемы "car-owner" (AIRPLANE наследуется от VENTILATION_SYSTEM). Они указывают, что этой ошибки просто избежать благодаря абсолютному критерию, не оставляющему места для сомнений или двусмысленности:
При схеме наследования, хотя наследуемые свойства являются вторичными, они все же являются свойствами всего объекта, описываемого классом. Если мы делаем AIRPLANE наследником COMPARABLE, то отношение порядка применимо к каждому самолету как к целому, но свойства VENTILATION_SYSTEM не таковы. Компонент stop VENTILATION_SYSTEM не прекращает полет самолета. |
Заключение в этом примере очевидно: AIRPLANE должен быть клиентом, а не наследником класса VENTILATION_SYSTEM.