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

How to handle abstraction and specialization of a class and its attributes?

为这个相当抽象的标题道歉。

更清楚:

我尝试将 Interface 对象传递给 Controler 构造函数,因此在我的 class 定义中 Interface 属性表示抽象基础 class .但是如果我的 Controler subclass A 需要调用 Interface A 的特定方法,则会引发编译错误,因为 Interface base class does'我没有这个方法。

我找到的唯一解决方法是调用 dynamic_cast,但显然它似乎是错误的。


这是我的 Interface classes:

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 classes:

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

下面是我打算如何使用它们:

auto ia = new InterfaceA();
auto ca = ControlerA(ia);
ca.commonMethod();  // Method defined in the base class
ca.uniqueMethod();  // Method defined in InterfaceA only

您可以在 Repl.it 上试用。

有什么设计模式可以解决这个问题吗?

确实有问题。 m_interface的动态类型与实现Controler的对象的动态类型之间存在不变量。但是Controlerclass无法维持这个不变量。所以 m_interface 成员不是正确的地方。

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

所以这不是真正的设计模式问题,而是更根本的面向对象编程建议:classes 必须确保不变量。

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