   OOP Design Questions - instanceof (Java to C++)
  Hello all, I have some questions regarding the design of OOP programs. Right now my program is written in Java and uses the instanceof operator. I have heard that there is a lot of taboo about this, mostly that using it is generally bad design. I am now moving this program over to C++ and since C++ doesn't have instanceof I want to design the code better.Right now, I have a game that has a lot of different objects that are stored in my World class. I have a lot of different interfaces such as Logicable, Drawable, Collidable, etc. etc.. Each object is added to a specific list where the methods are then handled by my World class. If this is confusing allow me to show you guys an example of where I use instanceof...public static void addObject(Object o){if(o instanceof Collidable){staticCollisionList.add((Collidable)o);}if(o instanceof SortedDrawable){sortedDrawableList.add((SortedDrawable)o);}if(o instanceof Logicable){logicableList.add((Logicable)o);}}Is this bad design? I am not sure how else I could achieve such ease in Java. Classes themselves are created, implement the interfaces they need, and then objects of the class can be added to the World using the above function and immediately run.Additionally if I want to achieve this in C++ how should I go about doing it? I am aware C++ uses multiple inheritance instead of interfaces. But what is the best method of storing and running objects which may have shared attributes. For example, if I had an Actor (updates, draws, and collides) and a Light (updates, draws), and a CollisionBox (draws, and collides) how should I keep track of and handle these?Thanks.   
Quote:Original post by evilsantaIs this bad design?IMHO, in most cases yes.Quote:I am not sure how else I could achieve such ease in Java.The key question here is:- Where does o come from?- Does it need to be opaque type?If it is an opaque type over whose creation you have no control, then this is often the only reasonable way to do it.Quote:Classes themselves are created, implement the interfaces they need, and then objects of the class can be added to the World using the above function and immediately run.Additionally if I want to achieve this in C++ how should I go about doing it?struct Foo {  Foo(World * world);};struct Collidable : public Foo {  Collidable(World * world) {    world->staticCollisionList.push_back(this);  }};struct World {  std::vector<Collidable *> staticCollisionList;  std::vector<SortedDrawable *> sortedDrawableList;  ...};This works in Java as well. Let the object itself figure out where it wants to belong. Alternatively, if you can't know where it will belong at construction, add a virtual install(World *) method.The constructor approach is my preferred one for component systems since it implicitly takes care of some life cycle issues.This design does require 1:1 mapping between components (its base interface at least) and world (world needs to know all possible interfaces), but it also simplifies many aspects. In practice, there shouldn't be too many different interfaces (10,20), even if there are many more distinct implementations.   ;  In general, the reason why instanceof() (and using other RTTI systems in program logic) are frowned upon is because they can be difficult to maintain. Every time you add a new class to the hierarchy, or change it (even if in this case, the problem is restricted to the upper levels), you now have to check all the places that might be affected. This code could be scattered all over your program, making it possible that you will forget one (or more!) area.But in this particular case, you may be fairly sure you are not going to introduce more interfaces that the World class needs a special case for. In which case yours may be a brittle but acceptable solution.C++ makes the burden slightly easier, because there are no interfaces, only classes, and they can have code. Example:class Collidable;class SortedDrawable;class Logicable;class World{public:    void add(Logicable *);    void add(Collidable *);    void add(SortedDrawable *);};class Collidable{public:    Collidable(World &world)    {  world.add(this);    }    virtual ~Collidable(){}};class SortedDrawable{public:    SortedDrawable(World &world)    {  world.add(this);    }    virtual ~SortedDrawable(){}};class Logicable{public:    Logicable(World &world)    {  world.add(this);    }    virtual ~Logicable(){}};// I haven't had reason to use multiple inheritance recently// So I can't remember if this is the correct syntax.class GameObject:    public Logicable,    public Collidable,    public SortedDrawable{public:    GameObject(World &world)    :  Logicable(world),  Collidable(world),  SortedDrawable(world)    {    }};That is just to show that you could do it. I wouldn't use this way. I think it would be better to use composition over inheritance for this. That is, an Object might have a Logicable, Collidable and SortedDrawable members, perhaps represented as boost::optional<> or a smart pointer of some description.Another design issue with your code is the keyword "static" in addObject(). Shouldn't World be a class rather than a namespace, given that it has state?Miscellaneous points:Quote:I am now moving this program over to C++ and since C++ doesn't have instanceof I want to design the code better.C++ does have an equivalent of instanceof (at least for types with virtual functions). It is dynamic_cast<>. It also has typeid(), but that is a pain.Quote:I am aware C++ uses multiple inheritance instead of interfaces.Not really. Most C++ code does not use multiple inheritance at all. C++ sometimes has totally different idioms for dealing with some issues.For example, the Java interface "Comparable" is used for comparing objects by the standard library in Java. Some allow a custom comparator, but this still must derive from a specific base class. In C++, library functions like std::sort are templates, and they take a comparison functor. The functor defaults to being std::less, which is defined for types that have an overload of the operator <().This is an example of how C++ achieves the same thing as Java without using inheritance at all.   ;Quote:Original post by evilsantaIs this bad design?It is, it violates the Open-Closed Principle.Quote:Additionally if I want to achieve this in C++ how should I go about doing it?Realistically there are a lot of ways to achieve this; you could use factory functions to create an entity however is necessary and register its components with the suitable lists:entity * create_actor(/*params*/){    entity * e = new entity(/*params*/);    register_collidable(e, /*other params*/);    register_drawable  (e, /*other params*/);    register_logicable (e, /*other params*/);    return e;}entity * create_light(/*params*/){    entity * e = new entity(/*params*/);    register_drawable  (e, /*other params*/);    register_logicable (e, /*other params*/);    return e;}entity * create_box(/*params*/){    entity * e = new entity(/*params*/);    register_collidable(e, /*other params*/);    register_drawable  (e, /*other params*/);    return e;}void register_collidable(entity * e, /*params*/){    collidable_list.push_back( collidable(e, /*params*/) );}void register_drawable(entity * e, /*params*/){    drawable_list.push_back( drawable(e, /*params*/) );}void register_logicable(entity * e, /*params*/){    logicable_list.push_back( logicable(e, /*params*/) );};  Thanks for all the help everyone, this has hopefully set me on the correct path.I did some reading on composition and I was wondering, if an Actor has a Collidable, Drawable, and a Logicable object, how would I cycle through all the possible Drawables stored in my World? Would I just have the Drawable constructor automatically add itself to the world?Additionally in this case it seems like it would be best if an Actor extended Logicable, since an Actor could have many things that could occur during a logic update (such as motion) whereas another class such as Light, would not move but perhaps flicker during its logic update, however an Actor and a Light would both have a Drawable and Collidable object. I am not sure if this is correct reasoning, but I guess I should just get coding and see what works best.[Edited by - evilsanta on April 25, 2009 5:16:29 PM];Quote:Original post by evilsantaThanks for all the help everyone, this has hopefully set me on the correct path.I did some reading on composition and I was wondering, if an Actor has a Collidable, Drawable, and a Logicable object, how would I cycle through all the possible Drawables stored in my World?Iterate ("cycle") through Actors, telling each to do something with its Drawable.And could you please think of something nicer-sounding than "Logicable"? :) I would say "Updateable", but it doesn't *have* to be a -able, either.Quote:Additionally in this case it seems like it would be best if an Actor extended Logicable, since an Actor could have many things that could occur during a logic update (such as motion) whereas another class such as Light, would not move but perhaps flicker during its logic update, however an Actor and a Light would both have a Drawable and Collidable object. I am not sure if this is correct reasoning, but I guess I should just get coding and see what works best.The amount of stuff that happens has nothing to do with it. What matters is the logic of the design: inheritance is meant to say the subclass instances are a special kind of the superclass (i.e., we follow the LSP: we could reasonably give a subclass instance to anything that expects an instance of the superclass), and composition is meant to say that the composer logically has the component as, well, a component.Years of experience have shown that it is generally easier to misuse inheritance where composition should be used, than the other way around.   ;  Or, have the Drawables add themselves to a list of Drawables, which is in an object contained by the world. Or, have Drawables only accessible by a factory/registry, which also "does stuff" to them, like drawing them. The latter approach also allows you to have multiple groups of Drawables at the same time, if for some reason you wanted that. You may find this thread interesting: Outboard Component-Based Entity System. Make sure you have some time before you start reading it, as it has five very long and dense pages.   ;Quote:Original post by ZahlmanAnd could you please think of something nicer-sounding than "Logicable"? :) I would say "Updateable", but it doesn't *have* to be a -able, either.My apologies, I just got used to having all interfaces ending in -able, and Logic sounds cooler. :)Either way, I am attempting to build a small text based example of my game using composition. I am finding that using composition seems to take more time to do things. I am not quite sure I understand the advantages of this over multiple inheritance.In my game, I need to be able to easily create an object that can collide. In my Java application I simply added all objects which were Collidable to a list of Collidable objects. So if I wanted to create a new class, for example Wall. I would simply implement Collidable and then it would instantly be able to collide with everything when passed to my World class. I am not sure how something similar can be achieved with composition, since if I have Wall contain a Collidable object how does the world know that the object added to it has a Collidable object?Would I just do something like what Antheus suggested and have each individual component (Collidable, Drawable, etc.) add themselves to the appropriate World list? Or should I only be adding Wall to the World?I guess I am just unsure why composition is superior to inheritance as it seems like it takes more work.Edit: Woops, missed your post theOcelot I think that answers my question. Ill look into that article.Additionally however, lets say I want classes to run during a logic update. I don't think an Actor should have a Logic object, because how would Actor customize the Logic objects update method? If I say, wanted to have an Actor to move left, Actor would normally just over-ride the update method and add in x--. But I am not sure how this would be done with composition, I am going to guess that this is a case where inheritance would be ok?   ;  Yeah, the main sticking point for me of Component-based design is the whole logic/control thing. How does an object manipulate its owner and siblings in a clean way?I'm convinced, though, that there is a good way to do it. The possibilities of a component-based controlling system are numerous and attractive. You could have an Actor controlled by either a hard-coded AI, a script, user input, or even a pre-recorded series of actions, as in a replay system, all with the same interface. You could easily drop any controller into, say, the main player Actor, or allow the user to take control of some other object, all almost painlessly.I've toyed with various ideas involving callbacks, message queues, and stuff, but haven't figured out a good way to do it. Maybe someone here can tell us how they do it?   ;Quote:Original post by evilsantaMy apologies, I just got used to having all interfaces ending in -able, and Logic sounds cooler. :)What about Controllable? It has the benefits of being a well understood term as well as being a real word.Quote:I am finding that using composition seems to take more time to do things.Take it as a good sign; composition is harder to achieve than inheritance but has the benefit of not promoting such a strong coupling.Quote:I am not sure how something similar can be achieved with composition, since if I have Wall contain a Collidable object how does the world know that the object added to it has a Collidable object?If your entity aggregates components (as a vector of pointers to components for example) then you can just iterate that list and register components to wherever is appropriate.Another option is to have components register themselves up on construction, a-la Antheus' example.Alternatively you could have the entity register it's own components when that entity is added to the world (with composition the entity knows what components it has).There is also the option of having the desired components registered, when an entity is contructed, by some sort of factory that creatures that entity, a-la my example above.Finally you could construct the entity and then notify the component lists of this new entity, then will then create suitable components for that entity (or ignore the notification if a particular entity doesn't require such a component).Quote:Additionally however, lets say I want classes to run during a logic update. I don't think an Actor should have a Logic object, because how would Actor customize the Logic objects update method? If I say, wanted to have an Actor to move left, Actor would normally just over-ride the update method and add in x--. But I am not sure how this would be done with composition, I am going to guess that this is a case where inheritance would be ok?You can specialise (inherit from) the logic component and override its update function - this lets you both customise the behaviour and maintain logic as a separate component.   