Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Use Interfaces Instead of Abstract Classes With DI?

I am beginning my journey of learning about dependency injection, and one of the reasons that I saw why it is a good idea to use DI was that it explicitly specifies your dependencies, which also makes your code more clear.

I have also noticed that interfaces are used abundantly, but I want to know why would we not use abstract classes for the sole purpose of specifying a default constructor?

Of course no implementation could be included in the abstract class.

Wouldn't this:

abstract class FooBase
{
    protected IBar _bar;

    FooBase(IBar bar)
    {
        _bar = bar;
    }

    abstract void DoSomething();
    abstract void DoSomethingElse();
}

Demonstrate more clearly what the dependency of a FooBase object is more than:

interface IFoo
{
    IBar Bar { get; }

    void DoSomething();
    void DoSomethingElse();
}

?

Please keep in mind I am new to this whole concept so be nice :)

like image 377
ChandlerPelhams Avatar asked Jul 19 '12 21:07

ChandlerPelhams


People also ask

When interfaces are better than abstract classes?

An interface is better than a abstract class when you want multiple classes to implement that interface and when you don't have to inherit default behavior.

Why do we use interface in dependency injection?

Doing so allows you to replace, intercept or decorate dependencies without the need to change consumers of such dependency.

Can we use abstract class instead of interface in dependency injection?

As always, the answer is: "It depends." You can't do these approaches with interfaces as interfaces only specify the contract and don't have implementation. If the contract is all you need, then go with an interface. If you need code to be shared by the subclasses, then go with an abstract class.

Why are interfaces better than classes?

A class can be instantiated i.e, objects of a class can be created. An Interface cannot be instantiated i.e, objects cannot be created. Classes does not support multiple inheritance. Interface supports multiple inheritance.


1 Answers

One technical reason - forcing particular parent class in languages without multiple inheritance (Java/C#) will significantly restrict freedom of implementation of the "interface".

Note that there are 2 concepts hidden behind "interface" word and it sort of make it harder to reason in C#:

  • "interface" and abstract concept: well defined set of properties/methods to interact with an object; contract to work with an object.
  • "interface" as type in particular language (C#/Java) - one possible representation of contract in given language.

Abstract/concrete classes can be used to represent contract, but force restrictions on implementers of contract in C#.

Some other languages (like C++) don't have such restriction and abstract classes is good option there. Other languages (i.e. "duck-types" JavaScript) does not have such class/interface distinction, but you can still have "contract" with an object.

Sample:

To provide more context where you should be hitting this restriction yourself in C#: DI is commonly used along with some form of TDD or at least with basic unit tests. So you try write some code and tests that uses abstract base class for DI.

abstract class Duck { 
  abstract void Quack();
}
class ConcreteDuck : Duck {...}

Now if you decide to write tests you may already have test classes that helps you to mock objects (if you are not using existing once)

class MockBase {...}

class MockDuck : MockBase,?????? // Can't use Duck and MockBase together...
like image 53
Alexei Levenkov Avatar answered Nov 15 '22 19:11

Alexei Levenkov