Need an opinion on inheritance versus composition

Started by
5 comments, last by mrbastard 12 years, 11 months ago
I have a class called OpenGLWindow. It does the window creation and all that stuff. Now is it wiser to make it have a function pointer that points to the render/reshape/event_handler so that the user can specify which render function it would use by using the get/set method, or should I use some other method like inheritance and have classes inherit the render/reshap/even_handler function? Or should I have a separate class say, Renderer/Reshaper/EventHandler, and have OpenGLWindow have those as members or something else?
Edge cases will show your design flaws in your code!
Visit my site
Visit my FaceBook
Visit my github
Advertisement
Generally prefer composition rather than inheritance.

Inheritance is a very strong relationship, the second strongest relationship in the C++ language. Using it implies that the object classes are so closely related that they are fully interchangeable. Are your objects that closely related?


You seem to just have a few events or function calls. If that is the only thing you need in common, just a set of function pointers, you should probably provide it through common function names to access members, not through inheritance. That lets you plug in anything to respond to the events and gives a general-purpose interface.

Part of the power of inheritance is that you can build a collection of fully interchangeable objects with differing behavior. If all of these objects will be placed into common containers, possibly built through factory methods, and generally used interchangeably, and are not used as separate types of objects, then you have a case for making an ABC that specifies that interface.
Yes I see, using a FunctionPointer as I have been doing makes more sense than using inheritance. But should I go more OOP and create a separate interface for render/reshap/even_handler function or would FunctionPointer be the better solution in your opinion?
Edge cases will show your design flaws in your code!
Visit my site
Visit my FaceBook
Visit my github

But should I go more OOP and create a separate interface for render/reshap/even_handler function


That's an odd use of OOP: "a few objects happen to have three event handlers so they require inheritance, a very strong relationship".

Provide whatever interface is necessary to get the job done.

The general rule is to prefer composition over inheritance. It isn't an absolute mandate that you must use one over the other.

You get to make that decision as you develop programs, and the decision is your own. You get to decide, and you get to live with the consequences. It doesn't affect me or the others on the board.


If you believe that making the objects interchangeable through inheritance is the proper design, or that inheritance will be the most efficient for the humans writing the system in the long run, then go for it. Nobody knows the program better than you, and if that's your assessment then go with it. If you later change your mind and discover composition is the better route, you can lean on your compiler to help you make that change throughout your code fairly quickly.
No I think you have misinterpret my second question or I didn't quite get your post. This is what I meant.

class IRender{
virtual void render() = 0;
};
class IReshape{
virtual void reshape() = 0;
};
template<typename EventType = SDL_Event>
class EventHandler{
virtual void handleEvent(const EventType& e) = 0;
}

class OpenGLWindow{
private:
IRender render_;
IReshape reshape_
EventHandler<> eventHandler_
public:
//...
}


or just

class OpenGLWindow{
public:
typedef void (*FuncPointer)();
typedef void (*EventHandlerFunc) (const SDL_Event& e);
private:
FuncPointer _displayer;
FuncPointer _reshaper;
EventHanderFunc _eventHandler;
publc:
//...
};


I figured in the sense of OOP the first example would be more flexible because it has more of an 'identity'. But right now, I have it coded in the FunctionPointer route. I just wanted some advice on this situation.
Edge cases will show your design flaws in your code!
Visit my site
Visit my FaceBook
Visit my github
Using interfaces allows the client to provide stateful implementations, which is nice. Another alternative is to use something like boost::function<>, which is more flexible again. The first solution you proposed is decent, although I don't know if templating the event handler gains you anything.
I generally advise only using inheritance if you absolutely need runtime polymorphism. If you don't need polymorphism, or can get away with compile time polymorphism, don't use inheritance. wink.gif
[size="1"]

This topic is closed to new replies.

Advertisement