Eugen
Eugen

Reputation: 2990

Classes design with virtual methods

How would someone solve such a problem with classes and type as least as possible code? Here is what I have

Base interface for everything

    class IWindow
    {
    public: 
        virtual void Refresh() = 0;
// another 100 virtual methods
// ...
    };

This interface is used inside a library that has no idea about the concrete implementation.

Here is a version of the concrete implementation

    class ConcreteWindow : public IWindow
    {
    public:
        void Refresh() override {}
/// the other 100 overridden methods 
    };

Now we have another interface that adds some additional methods and also used inside that library.

class IDBDetail : public IWindow
{
public:
    virtual void DoDetail() = 0;

};

and here is the main problem, when we create the concrete inmplementation for it

class IGDBDetailWrapper : public IDBDetail, public ConcreteWindow
{
public :
    void DoDetail() {}
};

of course the concrete class IGDBDetailWrapper is abstract as well because it doesn't implement those 100 methods, but I don't wanna do that, I'd like just to reuse the implementation from ConcreteWindow, they are all working with the same window handle but this won't compile of course.

I can copy/paste those 100 methods from ConcreteWindow into IGDBDetailWrapper, but that's an overkill, cause I might have another 10 such new interfaces and concrete implementations.

What other pattern can I use here that would help solve the question and not re-implement those 100 methods again and again?

Thx

Upvotes: 4

Views: 136

Answers (6)

radix
radix

Reputation: 394

@bashrc is right, but it should be possible to solve the problem with virtual inheritance:

class ConcreteWindow : public virtual IWindow {...}

class IDBDetail : public virtual IWindow {...}

This Wikipedia article on virtual inheritance states the solution as well.

Upvotes: 3

user2807083
user2807083

Reputation: 2982

You can use virtual inheritance. If we ignore fact should IDBDetail inherit from IWindow or not, we could use virtual inheritance to solve problem with current architecture:

    class IWindow
    {
    public: 
        virtual void Refresh() = 0;
// another 100 virtual methods
// ...
    };

    class ConcreteWindow : virtual public IWindow
    {
    public:
        void Refresh() override {}
/// the other 100 overridden methods 
    };

class IDBDetail : virtual public IWindow
{
public:
    virtual void DoDetail() = 0;

};

class IGDBDetailWrapper : public IDBDetail, public ConcreteWindow
{
public :
    void DoDetail() {}
};

Now compiler will use implementation for your 101 abstract method from ConcreteWindow

Upvotes: 2

Dmitriy Zapevalov
Dmitriy Zapevalov

Reputation: 1357

It will not solve your problem, but at least you can redirect execution yourself:

class IGDBDetailWrapper : public IDBDetail, public ConcreteWindow
{
public:
    virtual void DoDetail() override { /*work here*/ }

    virtual void Refresh() override { ConcreteWindow::Refresh(); }
    //another 100 methods
};

You can make the block of such redirections as a compiler #DEFINE and repeat it as many times as you want.

Upvotes: 2

CoffeDeveloper
CoffeDeveloper

Reputation: 8315

First, if you are using Visual Studio there are refactoring tools that can help you with that automating what could be otherwise a tedious task, second:

To me is much pointless doing the same:

class IDBDetail : public IWindow
{
public:
    virtual void DoDetail() = 0;

};

I would do that instead

class IDBDetail
{
public:
    virtual void DoDetail() = 0;

};

Interfaces should be used to abstract away responsibilities, so cluttering a Interface with already hundreds of methods with additional methods is a symptom of bad design.

However you could leverage composition one time for all, so you create one time a class that resolve the problem for your, and you can later reuse that

class IDBDetailWithConcreteWindow: public IDBDetail{

    IWindow * concreteWindow;
public:
    IDBDetailWithConcreteWindow(IWindow * window){
        concreteWindow = window;
    }

    void Refresh() override{
        concreteWindow->Refresh();
    }
}

And finally in any derived class you have just to implement methods from IDBDetail

IGDBDetailWrapper: public IDBDetailWithConcreteWindow{
public:

   void DoDetail() override { }
}

The advantage with this solution is that if you have external constraints (like a bad designed pre-existing code base) you can still use it, while the upper solution will not work if you cannot change the IDBDetail interface.

Upvotes: 3

MindRoller
MindRoller

Reputation: 241

You have to override all the methods in abstract class, there is no other way. Actually you shouldn't create an abstract class of 100 methods here and that's it. Perhaps You can divide it in some smaller abstract classes? However, in this case IDBDetail should not inherit after IWindow and IGBDDetailWrapper also shouldn't inherit after IWindow - and we are here.

Upvotes: 2

bashrc
bashrc

Reputation: 4835

Your design is running into diamond problem.

Now we have another interface that adds some additional methods and also used inside that library.

 class IDBDetail : public IWindow { 
  public:
     virtual void DoDetail() = 0;

};

From the description of your IDBDetail interface looks like IDBDetail should not inherit from IWindow. If its just about adding additional functionality then IDBDetail need not be a IWindow. It just needs to understand the IWindow. For example in order to make a monkey do a special things, a trainer need not be a monkey.

Decorator pattern may be what you are looking for.

Upvotes: 3

Related Questions