1

I'm wondering about the differences between inheritance and composition examined with concrete code relevant arguments.

In particular my example was:

Inheritance:

class Do:
    def do(self):
        self.doA()
        self.doB()

    def doA(self):
        pass

    def doB(self):
        pass

class MyDo(Do):
    def doA(self):
        print("A")

    def doB(self):
        print("B")

x=MyDo()

vs Composition:

class Do:
    def __init__(self, a, b):
        self.a=a
        self.b=b

    def do(self):
        self.a.do()
        self.b.do()

x=Do(DoA(), DoB())

(Note for composition I'm missing code so it's not actually shorter)

Can you name particular advantages of one or the other?

I'm think of:

  • composition is useful if you plan to reuse DoA() in another context
  • inheritance seems easier; no additional references/variables/initialization
  • method doA can access internal variable (be it a good or bad thing :) )
  • inheritance groups logic A and B together; even though you could equally introduce a grouped delegate object
  • inheritance provides a preset class for the users; with composition you'd have to encapsule the initialization in a factory so that the user does have to assemble the logic and the skeleton
  • ...

Basically I'd like to examine the implications of inheritance vs composition. I heard often composition is preferred, but I'd like to understand that by example.

Of course I can always start with one and refactor later to the other.

1
  • Think design not coding. Composition relates an object to its component parts (car to body,wheels,etc.), whereas inheritance allows you to represent specialized sub-types of an object in a controlled fashion that promotes code re-use. I don't know the language you posted your question in so I can't provide a detailed answer, but regardless of the language, from an OO perspective, the two concepts have different design purposes, so the should not be confused and code ease should not be a factor. Design correctly regardless, I say.
    – NoChance
    Sep 1, 2012 at 9:59

5 Answers 5

6

Conceptually speaking, composition models "consists of" relationships, whereas inheritance models "is a".

Using the car analogy, "a car has wheels" is a textbook example for composition, and it makes sense to have a class Wheel, and a class Car with a property wheels of type Wheel[].

In theory, an example of inheritance would be "a truck is a vehicle": properties common to all vehicles can be implemented in class Vehicle, while those specific to trucks can be implemented in class Truck.

The truck example, however, also illustrates the problem of the inheritance approach: what if you have to make your vehicle class polymorphic not only for the vehicles purpose (passengers vs. freight), but also for fuel type? You'd have to create four classes to cover passenger cars and freight vehicles, as well as diesel vs. gasoline powered. Add another orthogonal property, and the number of classes doubles again. Worse yet, you have to decide which of these orthogonal properties comes first in the class hierarchy: is it Vehicle -> DieselVehicle -> DieselFreightVehicle -> Truck, or is it Vehicle -> FreightVehicle -> DieselFreightVehicle -> Truck? Either way, you have to duplicate some functionality, either the freight-specific things, or the diesel-specific things. The solution is to use composition anyway: A vehicle has an engine (which can be diesel- or gasonline-powered), and a cargo type (which can be passengers or freight); you don't need a truck class anymore, because your vehicle class can already model all sorts of vehicles by combining suitable engines and cargo types. Note that the components are still polymorphic, but the container object is not. The trick is to keep polymorphism one-dimensional, that is, each polymorphic hierarchy models one of many orthogonal properties, such as engine type, freight type, etc.

This is why people say "favor composition over inheritance"; of course you are still inheriting, but you have separated your inheritance into independent strains.

1

It's depends on the architecture and what you need to resolve.

In your example a client of your code if want to change the implementation of doA, and doB with the inheritance example would need to write a class that extends from MyDo but with composition, just initialize with a class which have the same interface.

Now you need to thing what are the code of.

Suppose the class D before call doA or doB call another methods to perform validation or configurations and then execute doA, the inheritance approach is good.(in this case the client never call doA if not another method that do things and then call doA)

Simple example: Class Component. Class window extends Component. The class component have methods that would be used in class Window, and suppose that you what to add a button of close always, then imagine that you need overwrite the method addChildrens() to add that button. But you never call addChildern() it is doing by the initialize method of Component Class, that have already a life cycle implemented. (Be aware this could be done with different approach)

For composite situation. MyDo use directly the doA or doB as services, so expect some interface, but need to be flexible, suppose doA and doB read data form some source. Then you can have different implementations of Do whit the different sources.

Simple example: MyDo is a log tool class and doA, doB method log the information. You can have different implementation do Do that log in diferents sources.

I'm be leave that are more examples, but in general it depends of what you need to do with your classes after.

1

When you use inheritance, a subclass depends on implementation details of its superclass. If the superclass implementation details change, the subclass could break even though its code doesn't change. When you use composition you're not dependent on the implementation of a class, only its interface.

If the classes Do and MyDo are in the same package and under the control of the same programmers, it's generally safe to use inheritance. If you're aware of the dependencies, you can test the classes together when the superclass implementation changes. If you're extending a class that's not under your control (like a class from a standard library) you want to use composition so that a change in implementation details of the library class won't break your client code.

0

An important thing to mention is that inheritance should not be for the sole purpose of code re-use, use delegation/composition for this.

Composition would be when we have a class say BroadbandConnection with a method called connection(). Then your manager says we want to add encryption, so you create a class BroadbandConnectionWithEncryption. Your natural instinct may be to use inheritance and then make the new class BroadbandConnectionWithEncryption derive from BroadbandConnection.

Drawback's to this is that the creator of the initial class had not designed it for inheritance so you would need to change its definition to make the method connection() virtual so you can override its behavior in the derived class. This is not always ideal. A better idea is to use delegation here for the purpose of code reuse.

class BroadBandConnection
{
   public:
   void Connection (string password)
   {
      //connection code.
   }
};

class BroadBandConnectionWithEndcryption
{
   public:
   void Connection (string password)
   {
       mbroadbandconnection.Connection(password);
       //now do some stuff to zero the memory or
       //do some encryption stuff
   }

   private:
   BroadBandConnection mbroadbandconnection;
};
-1

Inheritance: Clients deal with instances of MyDo (or other subclasses). They choose the behavior they want by selecting a given subclass and using it. Best choice when you want to deliver a predetermined and immutable set of behaviors to the client.

Composition: Clients deal directly with instances of Do. They can choose he behavior they want by configuring the object, or by using an appropriate factory method. They may even change an object's behavior by reconfiguring it on the fly. Best choice when you want to give the client freedom to customize an object.

Imagine that you're an automobile manufacturer. You've got three models: Scoot, Zip, and Fly. All three are based on a common chassis and drive train (which you call Base internally) but have different body styles, interiors, etc. You don't sell Base as a product; it's just the foundation for the models that you do sell and not even manufactured as a separate assembly, it's just the common set of characteristics that the three models share. Scoot, Zip, and Fly are complete packages -- they're like subclasses of Base. All three models are available with various dealer installable options: sunroof, stereo, rocket boosters, etc.

When deciding between inheritance and composition, consider what you want to provide to users. Do you want a given feature to be baked into the product like the wheel base, or do you want it to be a dealer installable option, like a navigation system? Sometimes the choice is obvious; other times it's a matter of design choices.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.