Click here to Skip to main content
Click here to Skip to main content
Go to top

Implementation inheritance vs. DI

, 24 Oct 2013
Rate this:
Please Sign up or sign in to vote.
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:

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

Usage:

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:

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:

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:

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:

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)

Share

About the Author

Artem Elkin
Software Developer (Senior) GDC
Russian Federation Russian Federation
No Biography provided

Comments and Discussions

 
QuestionFor More : PinmemberMember 1033640130-Oct-13 17:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 24 Oct 2013
Article Copyright 2013 by Artem Elkin
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid