4.9 Является им или имеет его? — Наследование против агрегации

Предыдущая  Содержание  Следующая V*D*V

Наше представление окружности содержит представление точки в качестве первого компонента struct Circle:

 

struct Circle { const struct Point _; int rad; };

 

Тем не менее, мы добровольно решили не обращаться к компоненту напрямую. Вместо этого, когда мы хотим унаследовать, выполняем повышающее приведение из Circle обратно в Point и имеем здесь дело с начальной struct Point.

Существует ещё один способ представления окружности: она может содержать точку в качестве агрегата. Мы можем обрабатывать объекты только через указатели; таким образом, это представление окружности будет выглядеть примерно так:

 

struct Circle2 { struct Point * point; int rad; };

 

Эта окружность больше не выглядит как точка, то есть она не может унаследовать от Point и повторно использовать её методы. Она может, однако, применять методы точки к своему компоненту "точка"; просто невозможно применять методы точки к себе.

Если язык имеет явный синтаксис для наследования, различие становится более очевидным. Подобные представления могли бы выглядеть в C++ следующим образом:

 

struct Circle : Point { int rad; }; // наследование

 

struct Circle2 {

    struct Point point; int rad;    // агрегация

};

 

В C++ не обязательно получать доступ к объектам только через указатели.

Наследование, то есть создание подкласса от суперкласса, и агрегация, то есть включение объекта в качестве компонента какого-либо другого объекта, обеспечивают очень похожую функциональность. Какой подход использовать в той или иной разработке часто можно решить с помощью теста является им или имеет его?: если объект нового класса очень похож на объект какого-либо другого класса, следует использовать наследование для реализации нового класса; если объект нового класса имеет объект какого-либо другого класса как часть своего состояния, следует встроить агрегат.

Поскольку по отношению к нашим точкам окружность выглядит просто как большая точка, поэтому мы и использовали наследование, чтобы создать окружности. Прямоугольник неоднозначный пример: можно описать его через опорную точку и длины сторон, или же можно использовать концы диагонали, или даже три угла. Только при использовании опорной точки прямоугольник представляет собой какую-то воображаемую точку; другие представления приводят к агрегатам. В наших арифметических выражениях можно было бы использовать наследование, чтобы получить бинарный узел оператора от унарного, но это существенно бы нарушило проверку.

 

Предыдущая  Содержание  Следующая