如何处理类及其属性的抽象化和专业化?

时间:2018-12-03 15:11:33

标签: c++ design-patterns polymorphism abstract-class abstraction

为这个抽象头衔致歉。

更清楚:

  • 我有两个类1 -> 2 -> 3 -> ... 9 -> NULLControler(具有硬件意义,与设计模式无关)
  • 两者都是抽象的,带有一些纯虚拟方法,因此打算被子类化
  • 我需要将每个创建的Interface与一个Controler对象相关联
  • 每个Interface子类仅适用于Controler子类的子集(InterfaceControlerA + InterfaceA,但不适用于ControlerB + InterfaceB
  • 每个ControlerA + InterfaceB子类都有自己的不继承的方法(这就是为什么Interface只有一种可以使用它的原因)
  • Controler基类需要调用基类Controler的某些方法

我尝试将Interface对象传递给Interface构造函数,因此在我的类定义中,Controler属性表示抽象基类。但是,如果我的Interface子类A需要调用Controler A的特定方法,则会由于Interface基类不拥有此方法而引发编译错误。

我发现的唯一解决方法是致电Interface,但这显然是错误的。


这是我的dynamic_cast类:

Interface

这是我的class Interface { public: Interface() {}; virtual void method() = 0; }; class InterfaceA : public Interface { public: InterfaceA() : Interface() {}; void method() override { cout << "A overriding" << endl; } void onlyA() { cout << "A only" << endl; } }; class InterfaceB : public Interface { public: InterfaceB() : Interface() {}; void method() override { cout << "B overriding" << endl; } void onlyB() { cout << "B only" << endl; } }; 类:

Controler

这是我打算使用它们的方式:

class Controler {
public:
  Controler(Interface* i) : m_interface(i) {};
  virtual void uniqueMethod() = 0;
  void commonMethod() { m_interface->method(); }
  Interface* m_interface;
};

class ControlerA : public Controler {
public:
  ControlerA(InterfaceA* i) : Controler(i) {};
  void uniqueMethod() override {dynamic_cast<InterfaceA *>(m_interface)->onlyA();}
};

class ControlerB : public Controler {
public:
  ControlerB(InterfaceB* i) : Controler(i) {};
  void uniqueMethod() override {dynamic_cast<InterfaceB *>(m_interface)->onlyB();}
};

您可以在Repl.it上试用。

是否有解决此问题的设计模式?

1 个答案:

答案 0 :(得分:2)

确实有问题。在m_interface的动态类型和实现Controler的对象的动态类型之间存在不变性。但是Controler类无法维护此不变性。因此,m_interface成员不是正确的位置。

其结果是,您需要在运行时每次调用dynamic_cast时使用uniqueMethod来检查此成员的类型正确。如果不变量被破坏,则代码将具有UB,因为它将取消引用空指针。

因此,这实际上不是设计模式问题,而是从根本上讲是面向对象的编程建议:类必须确保不变性。

class Controler {
public:
  virtual void uniqueMethod() = 0;
  virtual void commonMethod() = 0;
};

class ControlerA : public Controler {
public:
  ControlerA(InterfaceA* i):m_interface{i} {
    assert(dynamic_cast<InterfaceA*>(i)!=nullptr);
    };
  void uniqueMethod() override { m_interface->onlyA();}
  void commonMethod() override { m_interface->method(); }
private: InterfaceA* m_interface;
};

class ControlerB : public Controler {
public:
  ControlerB(InterfaceB* i):m_interface{i} {
    assert(dynamic_cast<InterfaceB*>(i)!=nullptr);
    };
  void uniqueMethod() override { m_interface->onlyB();}
  void commonMethod() override { m_interface->method(); }
private: InterfaceB* m_interface;
};

因此,现在看来,我们有一个规则的模式,因此可以在这里考虑更通用的设计:

template<class Inter,void(Inter::* OnlyFunc)()>
class ControlerImpl : public Controler {
public:
  ControlerImpl(Inter* i):m_interface{i} {
    assert(dynamic_cast<Inter*>(i)!=nullptr);
    };
  void uniqueMethod() override { (m_interface->*OnlyFunc)();}
  void commonMethod() override { m_interface->method(); }
  private: Inter* m_interface;
};
using ControlerA = ControlerImpl<InterfaceA,&InterfaceA::onlyA>;
using ControlerB = ControlerImpl<InterfaceB,&InterfaceB::onlyB>;