Click here to Skip to main content
15,887,444 members
Articles / DI
Tip/Trick

Implementation inheritance vs. DI

Rate me:
Please Sign up or sign in to vote.
4.88/5 (5 votes)
24 Oct 2013CPOL1 min read 17.5K   6  
Thoughts of how implementation inheritance violates Dependency Injection and Dependency Inversion principles.

The term "interface" in computer science has slightly different meanings. Initially this meant just a public contract of the class. Some old OO programming languages even use this term for this purpose (see http://en.wikipedia.org/wiki/Objective-C#Interface). In languages like C# and Java the "interface" is a language feature that allows to define a list of method signatures separately from the classes themselves. Actually these two meanings are almost the same.

Let's assume we have a class:

C#
public class A
{
  public void M() {/*...*/}
  private void F() {/*...*/}
}

Usage:

C#
A a = new A();
a.M();

The method M is accessible for the client code and the method F is not. This works as if the compiler would create an invisible interface for the class A and rewrite the client code to work with this interface instead of the class A:

C#
public interface IInvisibleA
{
  void M();
}

public sealed class A : IInvisibleA
{
 private A() {}

 public static IInvisibleA New()
 {
   return new A();
 }

 public void M(){/*...*/}
 public void F(){/*...*/}
}

Usage:

C#
IInvisibleA a = A.New();
a.M();

The method F is still inaccessible even if it is public now. How to deal with implementation inheritance. Example:

C#
public class Base
{
  public virtual void M1() {/*...*/}
  public virtual void M2() {/*...*/}
}

public class Derived : Base
{
  public override void M2() {/*custom implementation*/}
  public void M3() {/*...*/}
}

This is equivalent to the following:

C#
public interface IInvisibleBase
{
  void M1();
  void M2();
}

public sealed class Base : IInvisibleBase
{
  public void M1() {/*...*/}
  public void M2() {/*...*/}
}

public interface IInvisibleDerived : IInvisibleBase
{
  void M3();
}

public sealed class Derived : IInvisibleDerived
{
  private readonly IInvisibleBase _base;

  public Derived()
  {
    _base = new Base();
  }

  //Automatically pasted by the compiler
  public void M1() { _base.M1(); }

  public void M2() {/*custom implementation*/}

  public void M3() {/*...*/}
}

Please note the Derived class constructor implementation. Obviously the _base is a dependency. And this dependency is hardcoded. So each time you use implementation inheritance you should take into account: this violates Dependency Injection and Dependency Inversion principles. Does it mean we should completely avoid the class inheritance? Not necessary, but our design decision should be reasonable. Inheritance doesn't necessary mean "best choice", "true OOP" etc. Often it is overused.

Useful links:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Luxoft
Poland Poland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --