OOP设计问题:继承与接口发现

时间:2022-09-16 11:14:31

Sorry for the lack of a better title; I couldn't think of a better one.

抱歉缺少更好的头衔;我想不出更好的一个。

I have a class hierarchy like the following:

我有一个类层次结构,如下所示:

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);
};

So far, so good.
Now it gets more complicated.

到现在为止还挺好。现在它变得更加复杂。

Components can support one or more types of simulation. (For example, a component that negates its input may support Boolean circuits as well as continuous-time simulation.) Every component "knows" what kinds of simulations it supports, and given a particular kind of simulator, it queries the simulator (via dynamic_cast or double dispatch or whatever means are appropriate) to find out how it needs to react.

组件可以支持一种或多种类型的模拟。 (例如,否定其输入的组件可能支持布尔电路以及连续时间模拟。)每个组件“知道”它支持哪种类型的模拟,并且给定特定类型的模拟器,它查询模拟器(通过dynamic_cast)或双重调度或任何适当的手段),以找出它需要如何反应。

Here's where it gets tricky:

这是它变得棘手的地方:

Some Components (say, imagine a SimulatorComponent class) themselves need to run sub-simulations inside of them. Part of this involves inheriting some properties of outer simulations, but potentially changing a few of them. For example, a continuous-time sub-simulator might want to lower its step size for its internal components in order to get better accuracy, but otherwise keep everything else the same.

一些组件(比如说,想象一下SimulatorComponent类)本身需要在它们内部运行子模拟。其中一部分涉及继承外部模拟的一些属性,但可能会改变其中的一些。例如,连续时间子模拟器可能希望降低其内部组件的步长以获得更好的准确性,但是否则保持其他所有内容相同。

Ideally, SimulatorComponent would be able to inherit from a class (say, SpecializedSimulator2) and override some subset of its properties as desired. The trouble, though, is that it has no idea whether the outer simulator's most-derived type is a SpecializedSimulator2 -- it may very well be the case that SimulatorComponent is running inside a more specialized simulator than that, like a SpecializedSubSimulator2! In that case, sub-components of SimulatorComponent would need to be able to somehow get access to the properties of SpecializedSubSimulator2 that they might need to access, but SimulatorComponent itself would not (and should not) be aware of these properties.

理想情况下,SimulatorComponent将能够从类(例如,SpecializedSimulator2)继承并根据需要覆盖其属性的某个子集。但问题是,它不知道外部模拟器的派生类型是否是SpecializedSimulator2 - 很可能是SimulatorComponent在比这更专业的模拟器中运行的情况,比如SpecializedSubSimulator2!在这种情况下,SimulatorComponent的子组件需要能够以某种方式访问​​他们可能需要访问的SpecializedSubSimulator2的属性,但SimulatorComponent本身不会(也不应该)知道这些属性。

So, we see we can't use inheritance here.

所以,我们看到我们不能在这里使用继承。

Since the only means in C++ for "discovering" sub-interfaces like this is dynamic_cast, that means the sub-components must be able to directly access the outer simulator themselves, in order to run dynamic_cast on them. But if they do this, then SimulatorComponent can't intercept any of the calls.

由于C ++中用于“发现”这样的子接口的唯一方法是dynamic_cast,这意味着子组件必须能够直接访问外部模拟器,以便在它们上运行dynamic_cast。但如果他们这样做,那么SimulatorComponent就无法拦截任何调用。

At this point, I'm not sure what to do. The problem isn't impossible to solve, obviously -- I can think of some solutions (e.g. hierarchical key/value dictionary maintained at run-time) -- but the solutions involves some massive tradeoffs (e.g. less compile-time checking, performance loss, etc.) and make me wonder what I should be doing.

此时,我不知道该怎么做。问题并非不可能解决,显然 - 我可以想到一些解决方案(例如在运行时维护的分层键/值字典) - 但解决方案涉及一些大规模的权衡(例如,更少的编译时检查,性能损失)等等)让我想知道我应该做什么。

So, basically: how should I approach this problem? Is there a flaw in my design? Should I be solving this problem differently? Is there a design pattern for this that I'm just not aware of? Any tips?

所以,基本上:我应该如何处理这个问题?我的设计有缺陷吗?我应该以不同方式解决这个问题吗?是否有一种我不知道的设计模式?有小费吗?

1 个解决方案

#1


0  

I'll try to give a partial advice. For the situation in which you need to use a simulator inheriting properties from some parent then a cloning function could be the solution. This way you can ignore what actually the original simulation was, but anyway you end up with a new one with the same props.

我会尝试给出部分建议。对于需要使用从某个父级继承属性的模拟器的情况,可以使用克隆函数作为解决方案。通过这种方式,您可以忽略原始模拟的实际情况,但无论如何,您最终会得到一个具有相同道具的新模拟。

It may just require some basic properties (like the simulation time step) which means you need to dynamic_cast to some intermediate class in your simulator hierarcy, but not exactly spot the right one.

它可能只需要一些基本属性(如模拟时间步长),这意味着您需要在模拟器层次结构中对dynamic_cast进行某些中间类,但不能完全找到正确的属性。

#1


0  

I'll try to give a partial advice. For the situation in which you need to use a simulator inheriting properties from some parent then a cloning function could be the solution. This way you can ignore what actually the original simulation was, but anyway you end up with a new one with the same props.

我会尝试给出部分建议。对于需要使用从某个父级继承属性的模拟器的情况,可以使用克隆函数作为解决方案。通过这种方式,您可以忽略原始模拟的实际情况,但无论如何,您最终会得到一个具有相同道具的新模拟。

It may just require some basic properties (like the simulation time step) which means you need to dynamic_cast to some intermediate class in your simulator hierarcy, but not exactly spot the right one.

它可能只需要一些基本属性(如模拟时间步长),这意味着您需要在模拟器层次结构中对dynamic_cast进行某些中间类,但不能完全找到正确的属性。