Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
roth_stephan_clean_c20_sustainable_software_development_patt.pdf
Скачиваний:
29
Добавлен:
27.03.2023
Размер:
7.26 Mб
Скачать

Chapter 6 Modularization

bool isSquare() const { return width == height;

}

//...

};

Favor Composition over Inheritance

But what can we do if an explicit class Square is uncompromisingly required, for example, because someone demands it? Well, if that is the case, we should never ever inherit from Rectangle, but from the Shape class, as depicted in Figure 6-4. In order not to violate the DRY principle, we use an instance of the Rectangle class for the Square’s internal implementation.

Figure 6-4.  The Square uses and delegates to an embedded instance of Rectangle

253

Chapter 6 Modularization

Expressed in source code, the implementation of this Square class would look like Listing 6-11.

Listing 6-11.  The Square Delegates All Method Calls to an Embedded Instance of Rectangle

class Square : public Shape { public:

Square() { impl.setEdges(2, 2);

}

explicit Square(const unsigned int edgeLength) { impl.setEdges(edgeLength, edgeLength);

}

void setEdgeLength(const unsigned int length) { impl.setEdges(length, length);

}

virtual void moveTo(const Point& newCenterPoint) override { impl.moveTo(newCenterPoint);

}

virtual void show() override { impl.show();

}

virtual void hide() override { impl.hide();

}

private: Rectangle impl;

};

Perhaps you’ve noticed that the moveTo() method was also overwritten. To this end, the moveTo() method must also be made virtual in the Shape class. We must override it, because the moveTo() inherited from Shape operates on the centerPoint of the base

254