Programming paradigms

The Partridge Family were neither partridges nor a family. Discuss.
albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Programming paradigms

Post by albinopapa » January 10th, 2016, 9:33 pm

I've been looking over programming paradigms recently and it's really not my first time doing so. The topic as of late is Inheritance vs Composition. Based on what I've read, this is a pretty advanced topic, and deals with code design. A lot of material I've read when I search "Inheritance vs Composition" seems to point to composition being the better option. Still, those for inheritance says it's only because programmers get the "idea" of inheritance wrong. The biggest example of misusing inheritance is for code reuse even of the derived/child class has nothing to do with the base class.

The opposition I've read to use composition over inheritance is two fold. One is inheritance breaks encapsulation, because child classes can access protected members of the parent class, and two is maintainability.

Another thing I've read concerning inheritance is the base/parent class should only be an Interface thus putting ALL implementation code in child classes. This supposedly increases maintainability with inheritance, but I don't really understand the reasoning.

Here are my questions and thoughts for discussion. I bring them here solely because this is the only coding community I belong to. I realize that a lot of you are either beginners or still learning like me, but perhaps something like this will help in the long run.
  1. Composition:
  2. What is it really?
  3. Is it just taking an object and making it a member of another object?
  4. If so, how is this comparable to inheritance?

    Inheritance:
  5. How is inheritance breaking encapsulation when that kind of seems like the whole point of inheritance by definition, to 'inherit' from? Child classes can't access the parent's private members directly, so there's still that encapsulation.
  6. Interfaces are base classes that have no implementations and no data members, there is no code reuse. I understand chili specifically pointed out NOT using inheritance specifically for code reuse and from what I have found forcing your code to do so always causes headaches.
This post really is poor, because I don't understand all the concepts that I want explained in greater detail, therefore, discuss...
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Programming paradigms

Post by albinopapa » January 10th, 2016, 10:01 pm

Example of headache for me.

Consider you have a Ship and you have a player and an AI that. Hmm, I'm already seeing an alternative to what I'm about to write, but I'll keep on the track I've set. The player and AI are ships, these ships have weapons and the weapons have ammo. I've had this instance before when Luis, Cameron and I were trying to make a game. AI, player and Ammo all inherited from an Entity class that stored the X, Y coordinates.

Ok, so here's probably an example of poor use of inheritance. Ammo has nothing to do with either AI or Player, which were ships that had ammo. We used inheritance to inherit Update and Draw functions and maybe a few others, plus the position members. We then had each child class have their own unique members and implementations of the derived methods. This is how I thought inheritance should be done, and still use this technique.

I suppose what we could have done was make Player and AI separate entities all together, which had an instance of a Ship* for the different types of ships and ship upgrades and such.

I'd love to have a solid example of what composition really is. Can't find any real world examples, just vague ones.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Programming paradigms

Post by albinopapa » January 11th, 2016, 5:39 pm

Just a curiosity for clarification on WHAT an example of composition would be.

We have covered vectors in the Advanced series, a vector can be considered a point or a magnitude + direction.

So would a class Player with a Vec2f pos be considered as composition? Since the _Vec2 class isn't just plain-ole-data (POD) it actually has methods so in a sense, it extends the Player class without Player actually deriving from it.

Or, something like class Player has a member class Ship and class Ship has a member class Weapon and class Weapon has a member std::list<Ammo>? Class Ship could actually be child classes of Ship that have different specifications by default with different derived classes of Weapon and those derived classes of Weapon would carry different derived classes of Ammo? That would be composition with inheritance, right?

I guess for me, if I'm right then chili has done his job as a teacher correctly. In the Player/Ship/Weapon/Ammo example, I wouldn't expect Weapon to inherit from Ship for example just to reuse a function or any other member, because they aren't related aside from Ship owning a weapon.

I suppose something like SniperRifle is a type of Gun with a Scope, so you could either inherit from Gun and add methods and fields in the SniperRifle class or you could make a SniperRifle class that has a Gun member and Gun would have an GunAddOn ptr. Then you could have another class called Scope that derives from GunAddOn that you pass an address to a Gun object.

Am I getting close?
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
LuX
Posts: 1492
Joined: April 22nd, 2012, 12:33 pm
Location: Finland

Re: Programming paradigms

Post by LuX » January 11th, 2016, 8:52 pm

If I understood right, I don't think the phrase "composition over inheritance" means choosing "composition" instead of "inheritance". Instead it means just what is says: composing something through inheritance.
Say you're working on a game that has a player, turret and mine:
A player is a visual entity, a moving entity and can cause damage
A turret is a visual entity and can cause damage ( but not move )
A mine can only cause damage.

You could structure this as:

Code: Select all

Damaging entities
{
    Mine;

    Visible entities
    {
        Turret;

        Moving entities
        {
            Player;
        }
    }
}
OR

Code: Select all

Damage class;
Visibility class;
Mobility class;

Player : private Damage, private Visibility, private Mobility;
Turret : private Damage, private Visibility;
Mine : private Damage;
So what's the big difference? Say at one point in your game you think: "You know what this game could really need? Ninjas!"
A ninja is an entity that can move and cause damage, but is not visible.

Looking at the first example, implementing the ninja brakes everything you have created so far.
Either you add it to the moving entities and ignore the visible part, which would be confusing or, you'd add a moving entity sub-class to damage class, which would be messy. Of course you could always write the entire code from scratch.

In the second example implementing the ninja is quite simple. You just add a new entity that inherits Damage and Mobility.

I think this style has a huge benefit in large projects that can change over time, because maintaining and adding things is simple. For a small project though it barely has any benefit and you might as well just define each entity individually, especially if each entity is almost or completely unique.
You'll know you're doing it wrong when you copy-paste the same function and write the same stuff over and over again for different entities.
ʕ •ᴥ•ʔ

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Programming paradigms

Post by albinopapa » January 11th, 2016, 10:26 pm

Huh, forgot about wide multiple inheritance, was only thinking of

Code: Select all

class Damage
{
}
class Visible :* Damage
{
}
class Moving :* Visible
{
}
// * Denotes public, protected or private


I noticed you used private inheritance, am I correct in saying that means if something inherits from those classes, they won't have access to the grandparents?

Code: Select all

class A
{};

class B :private A
{
	// B gets to see/use public and protected members of A
};

class C :private B
{
	// C can only see/use public and protected members of B ??
};
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
LuisR14
Posts: 1248
Joined: May 23rd, 2013, 3:52 pm
Location: USA
Contact:

Re: Programming paradigms

Post by LuisR14 » January 12th, 2016, 1:15 am

yea that's basicly what happens, plus can't access public members of the base from outside of the child
always available, always on, about ~10 years c/c++, java[script], win32/directx api, [x]html/css/php/some asp/sql experience. (all self taught)
Knows English, Spanish and Japanese.
[url=irc://irc.freenode.net/#pchili]irc://irc.freenode.net/#pchili[/url] [url=irc://luisr14.no-ip.org/#pchili]alt[/url] -- join up if ever want real-time help or to just chat :mrgreen: --

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Programming paradigms

Post by albinopapa » January 12th, 2016, 4:46 am

Awesome, thank you LuX and Luis. Now, I just need to play with it a little to make sure I'm getting it.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
LuX
Posts: 1492
Joined: April 22nd, 2012, 12:33 pm
Location: Finland

Re: Programming paradigms

Post by LuX » January 12th, 2016, 7:42 am

Ah, yes, I didn't give much though to it.
ʕ •ᴥ•ʔ

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Programming paradigms

Post by chili » January 13th, 2016, 12:33 am

I believe that using a component entity system can provide a lot more flexibility if architected well in the beginning, but I always seem to end up using inheritance in the end.

On of the challenges that I think you'll face when using a component-based system is how to get component peers connected and talking to each other in a clean and flexible manner.
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Programming paradigms

Post by albinopapa » January 13th, 2016, 5:30 am

Yeah, for me one of the nice things about public inheritance isn't just the code reuse, but being able to USE the members of a sibling without having to use accessor methods...I hate having to use the GetX() functions, unless it's getting a pointer to an array of data.

Something like: ArrayOfData *data = container.GetArrayOfData();

I understand the usefulness of encapsulation to prevent accidental manipulation of it, it just seems like a waste of CPU cycles.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply