Los Techies : Blogs about software and anything tech!

Refactoring Day 8 : Replace Inheritance with Delegation


All too often inheritance is used in the wrong scenarios. Inheritance should only be used in logical circumstances but it is often used for convenience purposes. I’ve seen this many times and it leads to complex inheritance hierarchies that don’t make sense. Take the following code:

   1: public class Sanitation
   2: {
   3:     public string WashHands()
   4:     {
   5:         return "Cleaned!";
   6:     }
   7: }
   8:  
   9: public class Child : Sanitation
  10: {
  11: }

In this instance, a Child is not a “Sanitation” and therefore doesn’t make sense as an inheritance hierarchy. We can refactor by initializing an instance of Sanitation in the Child constructor and delegating the call to the class rather than via inheritance. If you were using Dependency Injection, you would pass in the Sanitation instance via the constructor, although then you would need to register your model in your IoC container which is a smell IMO, you get the idea though. Inheritance should ONLY be used for scenarios where inheritance is warranted. Not instances where it makes it quicker to throw down code.

   1: public class Sanitation
   2: {
   3:     public string WashHands()
   4:     {
   5:         return "Cleaned!";
   6:     }
   7: }
   8:  
   9: public class Child
  10: {
  11:     private Sanitation Sanitation { get; set; }
  12:  
  13:     public Child()
  14:     {
  15:         Sanitation = new Sanitation();
  16:     }
  17:  
  18:     public string WashHands()
  19:     {
  20:         return Sanitation.WashHands();
  21:     }
  22: }

This refactoring comes from Martin Fowlers Refactoring book. You can view the original refactoring here

This is part of the 31 Days of Refactoring series. For a full list of Refactorings please see the original introductory post.

Kick It on DotNetKicks.com
Posted Aug 07 2009, 11:27 AM by schambers

Comments

Thomas Eyde wrote re: Refactoring Day 8 : Replace Inheritance with Delegation
on 08-09-2009 7:06 AM

This is a very useful refactoring. But, as always, there are these icky corner cases: I usually end up in the need of this refactoring, when I create new, but similar classes.

At first, it makes perfectly sense to extract super class. It's not until later, when I discover an unfortunate mix between orchestration and implementation, I see that delegation will make clearer code.

Reflective Perspective - Chris Alcock » The Morning Brew #408 wrote Reflective Perspective - Chris Alcock » The Morning Brew #408
on 08-10-2009 3:40 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #408

Scott Sherin wrote re: Refactoring Day 8 : Replace Inheritance with Delegation
on 08-11-2009 2:50 PM

Your example would be better refactored into an interface. Also why are you using a private property instead of just a private field? It's good to make all public variables into properties so if you need the flexibility later you don't break references. Private fields will have no references outside your class so you can refactor them into properties if needed.

The original example gets the idea across much better than this one.

张荣华 wrote 31天重构指南之八:用委派代替继承
on 09-28-2009 2:00 AM

有时继承老是被滥用,继承应该仅仅使用在逻辑环境(logical circumstances)中,但却经常因为编程的方便性被滥用,我见过许多因为滥用继承导致的复杂性增加,来看下面的代码: 1: publ...

31 Days of Refactoring « Vincent Leung's .NET Tech Clips wrote 31 Days of Refactoring « Vincent Leung's .NET Tech Clips
on 10-28-2009 9:28 AM

Pingback from  31 Days of Refactoring « Vincent Leung's .NET Tech Clips

PetterLiu wrote 31 Days of Refactoring
on 11-27-2009 4:01 AM

Refactoring Day 1 : Encapsulate Collection Refactoring Day 2 : Move Method Refactoring Day 3 : Pull ...

PetterLiu wrote 31 Days of Refactoring
on 11-27-2009 4:02 AM

Refactoring Day 1 : Encapsulate Collection Refactoring Day 2 : Move Method Refactoring Day 3 : Pull ...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems