Search Unity

Confused about Composition

Discussion in 'Scripting' started by Kensei, Aug 30, 2014.

  1. Kensei

    Kensei

    Joined:
    Apr 26, 2013
    Posts:
    63
    Hi, I've recently come across a hypothetical problem that I can't seem to solve. It came to me after I thought I grasped the whole concept of a HAS A relationship. Granted, I never had a liking to the inheritance style anyway, and apparently always had the composition mindset from the get go. Anyway, here's the problem:

    Lets say I have Car class and have created a game with 1000 cars. Now I want to add red cars and green cars, so naturally all I have to do is add a color property to my car object that's instantiated 1000 times. However, does that now mean that I have to go to through all my 1000 car instances in order to set the color? And then what happens if I want some of my cars (be they red or green) be unpurchasable (if thats a word)? Do I add an IPurchasable interface to the purchasable cars? Guess I just can't get the gist of how to properly use composition based objects.

    Any clarification would be most welcome.
     
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    I think you're as far from composition as it is possible to be...

    IS: Properties, a car has a color, a size, a price. "The care IS blue". Each of those are values without behaviours. There's no communication with a property. ( public Color paint; )

    IS A: Hierarchy. "The car IS A vehicle". Polymorphism. Functions and properties related to all vehicle go in the base class. ( public class Car : Vehicle { } )

    CAN DO: Interface, define a independent set of function a car can perform, like carry people, move, be interacted with. An interface is not related to a specific object. A door knob can also be interacted with. ( public class Car : Vehicle, IInteractive { } )

    HAS A: Composition. "The car HAS wheels", which have behaviour independent of the vehicle, but communicate with it. They spin, can turn, break and so on, but they are not the vehicle. The vehicle can call some of their functions. ( public Wheels[] wheels; )

    Composition shines best when combined with polymorphism. Here's a quick example;

    Code (CSharp):
    1. public abstract class Vehicle { }
    2.  
    3. public class Car : Vehicle
    4. {
    5.     public Motor motor;
    6.     public Wheel[] wheels = new Wheel[4];
    7. }
    8.  
    9. public abstract class Motor { }
    10.  
    11. public class V6 : Motor { }
    12.  
    13. public class V8 : Motor { }
    14.  
    15. public class Jet : Motor { }
    16.  
    17. public abstract class Wheel { }
    18.  
    19. public class WetTire : Wheel { }
    20.  
    21. public class DryTire : Wheel { }
     
    Last edited: Aug 30, 2014
    FabioHEPL and Kensei like this.
  3. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    I would think that yes, if each car can have its own color then you would have to set it for each one. But since you have 1000 instances you have to create anyway, you can set the property also that time.
    As far as being able to be purchased, you can use a bool property for that. I wouldn't use composition for color or purchasablility. Especially colors, which all cars have and is really only a color value.
    Composition is more for having behaviors or functionality that you can change on the fly, and encapsulate.

    Let's say you want some cars to honk, but others to beep. Instead of having a CanHonk bool and a CanBeep bool, you have a Honker property. Honker is a reference to a honker class which handles the sound.

    Public class honker
    Honker has an abstract method honkhorn()
    It could be an interface also.

    Public class beephonker:honker
    Void honkhorn()
    {
    Play clip "beep";
    }

    Public class honk honker : honker
    Void honkhorn()
    {
    Play clip "honk";
    }

    Public class nohonk: honker
    Void honkhorn()
    {
    Do nothing.
    }
    So now you have two different honker behaviors,plus one that is silent.

    So you have a car class. Typing this on my iPad spits sorta pseudocode.

    Public class car

    The constructor takes a honker class instance for color, purchasablility, and the type of honker:

    Car = new car (color.green, true, new beephonker())
    In the constructor, assign the honker to a honker property.
    And have a MakeSound method:

    Void Makesound()
    {
    Honker.honkhorn();
    }


    When you want the car to make a sound, you just call
    Car.Makesound();

    At any time, you can assign a different behavior to the honker property. Let's say it crashes and can't honk anymore. Just do this:
    Car.honker = new nohonk();

    I know this probably isn't the greatest example ever. But the benefit of composition is being able to change behaviors at any time. It's not fixed. And you don't have to have a block of code somewhere that says

    If green then play honk clip
    Else if red play beep clip
    If blue play ooogahclip
    But if crashed play no sound

    You just call MakeSound, and the right thing happens.

    Also...don't create individual instances of beephonker and such, for each car. I did that in my example, but it's not good. Use the singleton pattern, a single instance of each will do fine.
     
  4. Kensei

    Kensei

    Joined:
    Apr 26, 2013
    Posts:
    63
    Oh, I get it. I was somehow under the impression that in composition nothing should inherit. So HAS A only counts when the other object has separate behavior and isn't a property of the main object? So if a car had wipers, that would be a has a relation, and if a car had a brand that would be an IS relation ?

    So inside a car class I'd create all the needed parts, like engines, wipers and all, and then I derive from it when I want to make another car? I'm confused, this sounds like inheritance to me.

    If the general idea of composition is owning behaviors, then shouldn't classes be implemented with interfaces and constructors over deriving? Like when creating a new car it would take (engine,wiper,wheel) and then having an interface for the objects ability such as drivable,xplodable and so on.

    I have a feeling I'm going in circles in my head :D

    To sum it up, in composition I create and initialize all the objects in the base class, and in inheritance I do it on the derived classes. Is that correct?

    P.S: As for the singleton, I know the concept but everyone keeps saying how it's not thread safe so I'd rather not use it. I have no idea what threads do what in C#, not yet anyway :p
     
    Last edited: Aug 30, 2014
  5. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Composition and inheritance are not mutually exclusive, as they are not there to fix the same issue to begin with. You can use inheritance without composition, composition without inheritance, or both at the same time - like my example.

    You see, someone could code a car behaviour and every single sub-behaviour in one class. Like how the wipers work directly in the car class. He could then derive the car class into let's say "Honda" and override the wiper method and chance it's behaviour.

    However, in doing so, you bloat your class and make it a rigid tree. What is you want a Honda with the wiper of a Ford? What is you want to put a jet engine in your car? Having to write a new class for every possible combination of behaviour is possible... but horribly stupid.

    Component pattern is somewhat similar to Composition, only that composition explicitly define the base type it requires to work. Like a car needs 4 wheels, 1 engine, etc.

    Composition shines best when used in conjunction with inheritance (polymorphism).

    Here's the most powerful camera system in the world;


    It is a full-fledged composition system. "Positioner" is a base abstract class that define communication channels. From it, there's dozen other derived classes that define a specific behaviour on how a camera can be positioned in space. Since each parts are like legos - but lego with specific jobs - I can mismatch them endlessly! Every single camera behaviour you can think of, I can do it without coding new class; just by combining existing one in the system.

    Composition is taking a large complex system and breaking it down to smaller parts that are independent from each other, and interchangeable.
     
  6. Kensei

    Kensei

    Joined:
    Apr 26, 2013
    Posts:
    63
    Your lego analogy really resonated bro. I always thought of classes as legos, so basically instead of sticking everything in 1 spot and deriving from it, have separate classes for every behavior and then mix and match them in whatever I need? Is that all there is to it?
     
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Pretty much. The idea is just to get a good balance. You don't want to stick everything in one place, and you don't have to go down into too smaller pieces.
     
    Kensei likes this.