對不起,缺乏一個更好的標題;我想不出一個更好的。面向對象設計問題:繼承與接口發現
我有一個類層次結構如下所示:
class Simulator
{
public:
virtual void simulate(unsigned int num_steps);
};
class SpecializedSimulator1 : public Simulator
{
Heap state1; Tree state2; // whatever
public:
double speed() const;
void simulate(unsigned int num_steps) override;
};
class SpecializedSimulator2 : public Simulator
{
Stack state1; Graph state2; // whatever
public:
double step_size() const;
void simulate(unsigned int num_steps) override;
};
class SpecializedSubSimulator2 : public SpecializedSimulator2
{
// more state...
public:
// more parameters...
void simulate(unsigned int num_steps) override;
};
class Component
{
public:
virtual void receive(int port, string data);
virtual void react(Simulator &sim);
};
到目前爲止,一切都很好。
現在它變得更加複雜。
組件可以支持一個或更多類型的模擬。 (例如,否定其輸入的組件可能支持布爾電路以及連續時間模擬。)每個組件都「知道」它支持哪種模擬,並且給定特定種類的模擬器,它會查詢模擬器(通過dynamic_cast
或雙重派遣或任何適當的方式)來了解它如何反應。
這裏就是它得到棘手:
一些Component
S(比如,想象一個SimulatorComponent
類)本身需要運行它們的內部子模擬。其中一部分涉及繼承外部模擬的一些屬性,但可能會改變其中的一些屬性。例如,連續時間子模擬器可能想要降低其內部組件的步長以獲得更好的準確性,但其他條件保持不變。
理想情況下,SimulatorComponent
將能夠從類繼承(如SpecializedSimulator2
)並根據需要覆蓋其屬性的某些子集。麻煩的,不過,是它沒有想法外模擬器的最衍生類型是否爲SpecializedSimulator2
- 它很可能是SimulatorComponent
是更專門的模擬器比內運行,像SpecializedSubSimulator2
的情況下!在這種情況下,SimulatorComponent
的子組件需要能夠以某種方式訪問它們可能需要訪問的SpecializedSubSimulator2
的屬性,但SimulatorComponent
本身不會(也不應該)知道這些屬性。
所以,我們看到我們不能在這裏使用繼承。
由於在C++中爲「發現」子接口這樣的唯一手段是dynamic_cast
,這意味着該子組件必須能夠直接訪問外模擬器本身,以便對它們運行dynamic_cast
。但如果他們這樣做,那麼SimulatorComponent
不能攔截任何呼叫。
在這一點上,我不知道該怎麼做。問題不是不可能的來解決,顯然 - 我可以想到一些解決方案(例如在運行時維護分層鍵/值字典) - 但解決方案涉及一些大規模的折衷(例如較少的編譯時檢查,性能損失等),並讓我想知道我應該如何在做什麼。
所以,基本上:我該如何解決這個問題?我的設計有缺陷嗎?我應該以不同方式解決這個問題嗎?有沒有這樣的設計模式,我只是不知道?有小費嗎?
認真你就失去了我所有的模擬的東西。你可以採取另一個例子,比如遊戲對象或其他東西。聽起來你想要向上施放某些東西,但同時你不想這樣做。 –
@nilo:如果我試圖簡化它,然後人們不會明白的動機是什麼,所以我將最終得到的是沒有解決原來的問題的答案。 – Mehrdad