lundi 3 décembre 2018

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

Apologies for this quite abstract title.

More clearly:

  • I have two classes Controler and Interface (hardware sense, unrelated to design pattern)
  • Both are abstract with some pure virtual methods and hence intended to be subclassed
  • I need each Controler created to be associated with an Interface object
  • Each Controler subclass only work with a subset of Interface subclasses (ControlerA + InterfaceA or ControlerB + InterfaceB but not ControlerA + InterfaceB)
  • Each Interface subclass has its own methods not inherited (this is why only one kind of Controler can use it)
  • The Controler base class need to call some method of the base class Interface

I try to pass an Interface objet to the Controler constructor, hence in my class definition the Interface attribute represents the abstract base class. But if my Controler subclass A need to call a specific method of the Interface A, an compilation error is raised as the Interface base class doesn't own this method.

The only workaround I found was to call dynamic_cast, but it obviously seems wrong.


Here are my 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; }
};

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

And here is how I plan to use them:

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

You can try it on Repl.it.

Is there any design pattern to solve this issue?

Aucun commentaire:

Enregistrer un commentaire