Software Development

Replacing Inheritance with Composition

Quite a while back, I posted about how, despite the fact that you should prefer composition over inheritance, you can best design classes for inheritance. Now, I wish to give some examples of how you can take your code that uses inheritance and change it to use composition instead, which will often actually make your code more flexible.

The code will be in java, but the concepts can transferred to any language that is object-oriented. Some languages might have constructs that make parts of this easier, too (Kotlin’s Delegates).

One thing is important to remember, though: Even if you switch “completely” to composition, you will still have some inheritance. This inheritance will be from interfaces and interface-like classes only, though. It barely counts as inheritance, really, since all it’s doing is restricting itself to an API and not inheriting implementation details.

Basic Composition: The Delegate Pattern

The Delegate Pattern isn’t a very strictly-defined pattern, and you could even say that it is simply a synonym for composition. While the Adapter Pattern certainly qualifies as composition and definitely delegates to the wrapped object, I don’t consider it the Delegate Pattern. Some do, and that’s fine, but I prefer a more rigid definition where the delegate and wrapper implement the same interface. This is still fits most composition-based “patterns”, but it ignores the less obvious cases.

Well, let’s start with an interface that our code is going to be using. We’ll be using Foo as the interface.

public interface Foo
{
   void bar();
   int baz(int i);
}

Now we need a base implementation that we’ll be trying to inherit from before converting the relationship to composition instead. We’ll call it BasicFoo.

public class BasicFoo implements Foo
{
   public void bar()
   {
      System.out.println("method one called");
   }

   public int baz(int i)
   {
      return i * 2;
   }
}

Lastly, we need a class that inherits from BasicFoo. We’ll call it ComplexFoo.

public class ComplexFoo extends BasicFoo
{
   @Override
   public int baz(int i)
   {
      return super.baz(i) * 8;
   }
}

For the most part, ComplexFoo just inherits the implementation of BasicFoo, but it does make a verification of incoming arguments on baz().

So, what would it look like to change ComplexFoo to use composition instead of inheritance? Like this!

public class ComplexFoo implements Foo
{
   private Foo wrapped;

   public ComplexFoo(Foo wrapped)
   {
      this.wrapped = wrapped;
   }

   public void bar()
   {
      wrapped.bar();
   }

   public int baz(int i)
   {
      return wrapped.baz(i) * 8;
   }
}

Instead of inheriting from BasicFoo, ComplexFoo only inherits from the interface, Foo. In order to get access a base functionality, such as BasicFoo‘s, it accepts a Foo object in its constructor, and then delegates all the methods to that object, putting in the extra functionality before or after the delegation call, just you would if you were “delegating” via super.

Restricting the Delegate

What if you only wanted ComplexFoo to only be able to “extend” BasicFoo and no other base implementations? First off, this is very restrictive, so it probably shouldn’t be the case. But, if you have good reasons to go that route, you’ve got several options.

The first option is to only accept BasicFoos in the constructor. If BasicFoo is final (cannot be extended; this is actually very recommended, especially if you mostly do composition), this works, but if it’s not, you may end up with something that inherits from BasicFoo instead an actual BasicFoo object.

The second option is to hardcode it to make a BasicFoo in the constructor. Simply by seeing the word “hardcode”, you knew that this is not a recommended procedure.

My last option is to make the constructor private or package-private, still accepting any Foo object, and have a static factory method create the BasicFoo instance and pass it into the constructor. This way, you can pass in a test double of Foo in your tests if BasicFoo could be problematic for tests.

Replacing the Template Pattern

The simplest way to replace the Template Pattern is to use the Strategy Pattern instead. Often, I like to think that a Strategy object only has one public method, but that’s largely because it allows you to transform it to a lambda or method reference more easily. In truth, the Strategy Pattern allows the Strategy objects to implement many methods to fulfill its strategy interface. You may not suffer from this view of the pattern, but I thought I’d share it with you, just in case.

I suppose you would like an example, huh?

public abstract class Bar
{
   public int foo(int i)
   {
      i = bar(i);
      i = baz(i);
      return qux(i);
   }

   abstract protected int bar(int i);
   abstract protected int baz(int i);
   abstract protected int qux(int i);
}

Bar uses the Template Pattern, leaving some methods protected so that subclasses fill them in to be used by Bar‘s public methods. I hope I don’t have to give you an example subclass; if you’re confused about what the Template Pattern is, please look it up.

Let’s transform this Template Pattern into the Strategy Pattern:

public class Bar
{
   private BarStrategy strategy;

   public Bar(BarStrategy strategy)
   {
      this.strategy = strategy;
   }

   public int foo(int i)
   {
      i = strategy.bar(i);
      i = strategy.baz(i);
      return strategy.qux(i);
   }
}

Our new Bar class no longer has those protected methods to deal with. Instead, it accepts a BarStrategy and delegates to it for those calls.

I originally had a real life example of this idea, but then I realized that it was the Strategy Pattern. After that, I thought that any example wouldn’t really be all that helpful, since any example of the Strategy Pattern is an example of a compositionally engineered Template Pattern.

The Gains

So, what do we gain from shifting away from inheritance and towards composition? Well, we gain more code, since we often have to replace implicit delegation to the “super” class with explicit delegation calls (some languages will provide shortcuts to get around this, such as Kotlin’s Degelates). Yes, it’s a gain, but not a good one. What about real helpfulness?

The biggest thing that’s helpful about switching to composition instead of inheritance is the lack of what I like to call “combination hell”. This is the biggest problem that the Decorator Pattern was designed to get around, but any switch to composition helps with this. You come up with a class extension that provides a certain extra bit of functionality around the base functionality. Then you come up with another one with a different bit of functionality. Eventually, you realize you want a class with both. If you did this with inheritance, you’d need to create another class that combines them somehow. If you used composition, you have everything you need, since you can just have the one extension accept, wrap, and delegate to the other (which wraps the base class).

Another large benefit of using composition was mentioned earlier: testability. Now you can test just the new functionality of the class by making a dud of a test double to replace the “super” class. This testability is courtesy of following the SRP better.

Unfortunately, using composition will usually make creation of the objects a hair more difficult, needing to create instances of each intermediate object instead of just the specific subclass, but seeing as most creation should be done in some sort of Factory context, it’s not a problem you have to deal with a lot.

Avoiding Some Explicitness

I mentioned up above that composition requires a bit more explicitness to it than inheritance, since it requires you to fill in all the methods with delegation calls. I mentioned that some languages provide features that let you shortcut around this, but you can get around this in languages without such features if you’re willing to stretch my meaning of “interface-like classes” that I used above. Since my favorite pattern, the Decorator pattern, uses it, I’m willing to stretch it.

I’m referring to the creation of an abstract class whose whole purpose is to delegate. This is the Decorator base class in the Decorator pattern. It’s a fully fleshed-out – yet abstract – class that technically does nothing, since it delegates all of its calls to the wrapped object. I have no qualms with the creation of such a class to be inherited from. Since it essentially does nothing, it can be looked at as “interface-like”. The really nice thing about this is that you can inherit from it, and if you’re not making any changes to a method, you don’t need to include it.

Not only does this lead to shorter code, but it also follows the SRP better than composition was already doing: one class is used for explicit delegation, the other ones for ONLY adding the new functionality (and explicit delegation when needed). It also removes code duplication. It’s definitely worth the inheritance “coupling”.

Outro

That’s all I can give you about the wonderful world of “composition over inheritance”. There may still be some times when inheritance is still the best option, but I urge you to strongly consider composition before making that decision.

Reference: Replacing Inheritance with Composition from our JCG partner Jacob Zimmerman at the Programming Ideas With Jake blog.

Jacob Zimmerman

Jacob is a certified Java programmer (level 1) and Python enthusiast. He loves to solve large problems with programming and considers himself pretty good at design.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Serhiy Palamarchuk
Serhiy Palamarchuk
8 years ago

Good article, such programming principle exists “prefer composition over inheritance”. Though, 1st we need to consider the purpose of inheritance – acquiring common characteristics and behavior, this is useful for building a hierarchy (mentioned interface-like classes also), trees. Pretty straightforward examples – animal, vehicle etc, you cannot avoid inheritance overall and not because of just replacing with composition requires some interface-like classes. One more principle to be equipped with is “LSP – Liskov substitution principle” to check if inheritance can take place in particular case.

Jacob Zimmerman
8 years ago

While it’s true that, other than what I mentioned in my article, you can’t fully avoid inheritance, you’d be surprised how often it turns out to still be a better idea to use composition instead.
Your understanding of LSP seems like it might be a little narrow, since it applies to using composition as well, since it’s inheritance from an interface.

Serhiy Palamarchuk
Serhiy Palamarchuk
8 years ago

I’d not say narrow understanding of LSP as it states mainly about subtypes, i.e. in other words inheritance, of course composition may use inheritance as it is written by using interfaces/classes.

Back to top button