Рассмотрим этот случай специализации, когда менее специализированному классу требуется доступ к объекту типа интерфейса, но более специализированному классу требуется доступ к конкретной реализации этого интерфейса:
class IPropulsionMechanism {
public:
virtual void engage() = 0;
virtual void disengage() = 0;
};
class Engine : public IPropulsionMechanism {
};
class Vehicle {
public:
void travelTo(const Destination& dest) {
mPropulsion.engage();
dest.arrival().wait();
mPropulsion.disengage();
}
void SetPropulsion(IPropulsionMechanism& prop) {
mPropulsion = prop;
}
protected:
IPropulsionMechanism& mPropulsion;
};
class Car : public Vehicle {
void adjustTiming() {
// Propulsion Mechanism MUST be Engine
}
Проблема заключается в том, что автомобиль должен знать детали своего двигателя, он не может работать без него, и все же SetPropulsion
Метод принимает только тип интерфейса.
Некоторый унаследованный код до меня теперь решает эту проблему путем SetPropulsion
быть контравариантным (через dynamic_cast
в Engine
). Очевидно, этот актерский состав делает SetPropulsion
нарушать принцип Лискова.
Мое предварительное решение состоит в том, чтобы добавить Engine& mEngine
член подкласса, и SetEngine
метод:
void SetEngine(Engine& engine) {
mEngine = engine;
Vehicle::SetPropulsion(engine);
}
Однако мое единственное замечание заключается в том, что подкласс будет иметь доступ к двум ссылкам на одно и то же (mPropulsion и mEngine).
Обратите внимание, что в отношениях может быть много таких членов, для автомобиля требуется двигатель, CarSeat, AirConVentilation, &с. но транспортное средство должно иметь механизм движения, вентиляцию и вентиляцию, &с.
Я подозреваю, что есть шаблон, который уже охватывает эту специализацию. Надеюсь, кто-то может назвать это для меня.
Задача ещё не решена.
Других решений пока нет …