Jump to content
  • Advertisement
Sign in to follow this  
Heelp

Trouble switching from inheritance to composition.

This topic is 665 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all,

 

I just decided to cut down my 1000 year-old inheritance tree because of too many nasty problems you probably already know of.

 

But I'm trying to draw all the stuff in my head before starting to make such a big architectural change. Big for me, probably not so big for you.

 

Ok, let's imagine I've rewritten all my classes using composition.

 

The way I see it, my GameObject will look like this:

class GameObject
{
  Matrix transform;
  Model* model;
  Physics* physics;
  Renderer* renderer; //Or I'll just use a static void render(GameObject&) function instead of a whole class, for starters.
}

Ok, cool. But now I need a Player object.

class Player
{
  Input* input;
  Animator animator; //for skeletal animation
  Matrix transform;
  Model* model;
  Physics* physics;
  Renderer* renderer; //Or I'll just use a static void render(GameObject&) function instead of a whole class, for starters.
}

Imagine 10 more different classes like this.

 

Final step is to render all entities using a 'for' loop.

 

If I was using my bad old inheritance tree, I would just do:

for( auto& object : gameObjects ) { Renderer::draw( object, viewCamera, interpolationRatio ); }

And have no problems since every monster inherits from GameObject.

 

But now that I have 10 classes for 10 different monsters, how do I render them at once? :huh:

 

1. overloading the Renderer::draw() function doesn't count

2. Stuffing every component in the world in the GameObject and using flags doesn't count. It will become too fat, I'm sure.

3. Entity-component-system is too much. I just want to make a simple game like a normal person.

 

Heeelp! :o

 

And thanks for reading. :rolleyes:

Edited by codeBoggs

Share this post


Link to post
Share on other sites
Advertisement

Thanks to all for the replies. ^_^

 

WoopsASword, inheritance is not the way to go, man. Or maybe I'm just missing something, but I doubt it. I would really like to switch to using components.

 

I don't say inheritance is bad as a tool, it works, but it doesn't work when it becomes a big, fat tree that I'm afraid to inherit from, because I get loads of functionality that I don't want just so I can get 2 functions I need. And I always wonder whether I should copy/paste some code, or inherit, but I don't want multiple inheritance, and yeah...

 

Guys, I kind of like the idea of putting 100k components into GameObject and then if I want to use something, I just set the flag to true. The GameObject will be giant, but once I get used to it, I will be ok. Bear in mind that I don't have a team, so readability for others is not an issue. What do you think?

Edited by codeBoggs

Share this post


Link to post
Share on other sites
What do you think?

I think you should use the tools that are the best suited for what you want to achieve.

 

Inheritance represents "is-a" relationships. It's perfectly suited for when you want to model inheritance.

Composition represents "has-a" relationships. It's perfectly suited for when you want to model composition.

 

Swapping everything to composition or swapping everything to inheritance seems like a really bad idea. Use what's appropriate, when it's appropriate.

 

 If your problem is having a "big fat tree" that you're afraid to inherit from, that's a sign that you probably shouldn't inherit from it in that case.

Either because your base object is far too complex, or because the thing you are trying to model does not fit the inheritance model.

If you can guarantee something is common for absolutely everything, put that as the common object and inherit from that.

 

There are already some excellent answers in this thread, I would suggest you reconsider them instead of dismissing inheritance completely.

 

EDIT: That is to say... don't swap for the sake of swapping. Swap if and when there is a good reason to swap.

Edited by Lactose

Share this post


Link to post
Share on other sites

Lactose!, there are many reasons. I just can't code anymore man, my code is a mess. And I'm not productive.

 

For example, if I have a Character like this

class Character
{
  CollisionBox box;
  Health hp;
  Input* input;
  Animator animator; //for skeletal animation
  Matrix transform;
  Model* model;
  Physics* physics;
  Renderer* renderer; 
}

Imagine my character has the magic ability to become invisible, where he can go through walls and doesn't take hp.

 

So when the character is invisible, I would just like to remove the CollisionBox and Health out of the equation. With inheritance it's messy and ugly. But with composition, I can just remove the Health and the CollisionBox components when I'm invisible, and add them back when I'm visible, for example.

 

EDIT: Entity-component-system is shitty, because I don't want to put all of the behaviour in a system and leave the components to be just data, I mean who does that stuff??  <_<

And inheritance is ugly, not flexible or extendable and not readable, there's no argument about that. :angry: Talking about games here, not business stuff.

 

Need to come up with something else, but needs to be doable in C++, of course. :wacko:

Edited by codeBoggs

Share this post


Link to post
Share on other sites

I decided on switching to composition and putting both data and behaviour in the components. And if some data is shared by more than one component, I will declare it in the entity. But I will use shared variables only for the basic stuff, to keep the entity clean. And for the other stuff, I will just send messages between the objects somehow, will figure that out later. ^_^

 

EDIT: Now I decided to put all possible components in GameObject, and do like this:

  if (self.hasRender) {
    [self updateRender:dt];
  } 
  if (self.hasHealth) {
    [self updateHealth:dt];
  }
  if (self.hasTeam) {
    [self updateTeam:dt];
  }
  if (self.hasGun) {
    [self updateGun:dt];
  }
  if (self.hasMove) {
    [self updateMove:dt];
  }
  if (self.hasDamage) {
    [self updateDamage:dt];
  }
  if (self.hasPlayer) {
    [self updatePlayer:dt];
  }
  if (self.hasAI) {
    [self updateAI:dt];
  }
  if (self.hasHuman) {
    [self updateHuman:dt];
  }

Simple and cool for noobs like me.

Edited by codeBoggs

Share this post


Link to post
Share on other sites

Thanks to all for the replies. ^_^

 

WoopsASword, inheritance is not the way to go, man. Or maybe I'm just missing something, but I doubt it. I would really like to switch to using components.

 

I don't say inheritance is bad as a tool, it works, but it doesn't work when it becomes a big, fat tree that I'm afraid to inherit from, because I get loads of functionality that I don't want just so I can get 2 functions I need. And I always wonder whether I should copy/paste some code, or inherit, but I don't want multiple inheritance, and yeah...

 

Guys, I kind of like the idea of putting 100k components into GameObject and then if I want to use something, I just set the flag to true. The GameObject will be giant, but once I get used to it, I will be ok. Bear in mind that I don't have a team, so readability for others is not an issue. What do you think?

 

I personally prefer a "big fat tree" as long as it's properly designed.

You can't run away from complexity, some code are so complex you have to sit monthes just to understand it.

What can we as developers do? Simplify as much as we can! 

Your understanding of what "composition" should consist of is not well.

Composing objects should not interfer with your inheritance.

 

"100K components into "gameobject"" - This is not how it works.

If not all derived "gameobject" need these 100k objects, than It's not the place for these objects.

"readability for others is not an issue" - There's a special quote for that:

"When I wrote that only me and god knew what it does. Now?  only god".

 

EDIT:

 

I decided on switching to composition and putting both data and behaviour in the components. And if some data is shared by more than one component, I will declare it in the entity. But I will use shared variables only for the basic stuff, to keep the entity clean. And for the other stuff, I will just send messages between the objects somehow, will figure that out later.  ^_^

 

EDIT: Now I decided to put all possible components in GameObject, and do like this:

  if (self.hasRender) {
    [self updateRender:dt];
  } 
  if (self.hasHealth) {
    [self updateHealth:dt];
  }
  if (self.hasTeam) {
    [self updateTeam:dt];
  }
  if (self.hasGun) {
    [self updateGun:dt];
  }
  if (self.hasMove) {
    [self updateMove:dt];
  }
  if (self.hasDamage) {
    [self updateDamage:dt];
  }
  if (self.hasPlayer) {
    [self updatePlayer:dt];
  }
  if (self.hasAI) {
    [self updateAI:dt];
  }
  if (self.hasHuman) {
    [self updateHuman:dt];
  }

Simple and cool for noobs like me.

 

 

This is terrible.  

Edited by WoopsASword

Share this post


Link to post
Share on other sites
This is terrible.  

WoopsASword, I kind of disagree, man. And I will tell you why. My game will consist of maximum 30-40 components. This method may not be suitable for large-scale games, but saves a lot of developing time. And I'm doing a small game. In my opinion, there is no terrible code or pattern, there's just code that is not suited for the purpose. 

 

If you still don't agree with me, you can post and tell me why I'm wrong. I'm open to criticism.  ^_^

 

I think you should use the tools that are the best suited for what you want to achieve.

See, you said it. :cool:

Edited by codeBoggs

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!