Inheritance, Composition, WTF?

September 20th, 2007

Working with the code is not a piece of cake. Especially when one must read and understand "WTF an author had in mind?"
Every day I encounter good code, crazy ideas, stupid constructions and totally fucked up architecture. Unfortunately, the most common is inheritance used where it should not be. Maybe I am too touchy?

Let's assume that we have an object which should be accessible across a project (or among several classes). Normally it's a good idea to create a singleton / static class and initialize it with specified object. I often encounter another approach... I call it "composition by inheritance". There is a class which has the object as a field / property. Then any other class that can use that object... derive from a base class when this object is placed! It looks like below (do not pay attention for types - it's an example only):

C#:
  1. public class Foo
  2. {
  3.         public object SharedObject = new object();
  4. }
  5.  
  6. public class Bar : Foo
  7. {
  8.     public void DoSomething()
  9.     {
  10.         SharedObject.Consume();
  11.     }
  12. }

And the main question - what do you think about it? In my opinion inheritance does not serve this purpose. It should not be used like that because there is no polymorphism here and potential changes in a base class can have many unforeseen consequences.
Any other pros / cons?

6 Responses to “Inheritance, Composition, WTF?”

  1. Xion says:

    Usually mismatching composition and inheritance can be told by asking simple question: Is “A like B” or rather “A consists of B”. Here obvisouly Bar isn’t like Foo; its only using it for some implementation purpose. If C# had private inheritance, it could be used here. Not very appealing, but at least noone could use the fact that Bar derives from Foo. Here there is such possiblity.

    However, it’s not even the case to replace composition with inheritance, because here we DON’T have a composition – we have an assocation, a pretty unspecified realtion of classes where one ‘uses’ the another one. Thus the only viable option for me is explicitly provide reference to shared object in external code, for example via constructors of objects that are using the shared one.

  2. Reg says:

    Yes, I think you are absolutely right.

    First of all, I tend to avoid inheritance and I use it quite rarely – only when it makes both logical and technical sense, especially if I’m going to use polymorphism.

    Interitance should model the “is” relationship, as in “an apple is a kind of a fruit”. Composition should be used every time we have the “has” relationship in mind, like in “objects of Bar class have a reference to shared object”.

    Meyers writes about it in his great books. Anyway, it is a rule well known to all “object oriented programmers”. And your name “composition by inheritance” sounds great as new design anti-pattern! (Take a look at existing design antipatterns at Wikipedia, it’s fun :) )

  3. SirMike says:

    So, that’s true :) I know now that I’m dealing with a classic Yo-yo and BaseBean antipattern

    http://en.wikipedia.org/wiki/Yo-yo_problem
    http://en.wikipedia.org/wiki/BaseBean

  4. Wiktor Zychla says:

    Using inheritance you allow objects to access resources in a uniform way but they still do not share THE SAME instance of shared object!

    Consider two instances of Bar class from your example:

    Bar b1 = new Bar();
    Bar b2 = new Bar();

    they share SharedObject in a sense that both b1 and b2 can access SharedObject but both contain THEIR OWN instance of SharedObject.

    This does not have anything common with Singleton and sharing instances.

    I belive that there’s no way of instance sharing if you do not have “static” objects in your runtime environtment. I do not think it is possible to share an instance using inheritance only.

    Could you elaborate more on your example?

  5. SirMike says:

    Yes, you’re absolutely right but I think you don’t get me :) The name “SharedObject” does not mean that this object is shared. Look at this as if it was only one class and one instance.

    Let’s say that SharedObject of base class Foo contains data (for example the reference of currently logged user profile). Foo’s purpose is that the Bar class has easy access to this data and don’t need to call another class / helper method to get them.

    As I wrote in the initial post – it is stupid solution which has nothing to do with inheritance.

  6. Wiktor Zychla says:

    ok, I’ve missed the BaseBean antipattern reference ;) now I got ya.

Leave a Reply

Designed by SirMike © All rights reserved

Valid XHTML 1.0! Valid CSS!

Powered by Rootnode