Click here to Skip to main content
12,455,701 members (93,268 online)
Click here to Skip to main content
Add your own
alternative version

Stats

9K views
6 bookmarked
Posted

Implementation inheritance vs. DI

, 24 Oct 2013 CPOL
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) Luxoft
Poland Poland
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160826.1 | Last Updated 24 Oct 2013
Article Copyright 2013 by Artem Elkin
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid