Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do I use abstract classes versus interfaces with regards to dependency Injection?

I have been reading some articles about the SOLID principles and dependency Inversion. From my point of view, I must use an interface to talk to any class. My classes are chatting by using interfaces.

First Question:

I am using an abstract class but for the second part of my code, I use an Interface.

Usage1


namespace DependencyInjection
{

    public interface IMessage
    {

    }
    public abstract class Message
    {
        public abstract void Get();
        public abstract void Send();
    }

    public class Sms : Message, IMessage
    {
        public override void Get()
        {
            Console.WriteLine("Message Get!");
        }
        public override void Send()
        {
            Console.WriteLine("Message Send!");
        }
    }

    public class MessageManager
    {
        private IMessage _message;

        public Sms Sms
        {
            get { return _message as Sms; }
            set { _message = value; }
        }

        public MessageManager(IMessage message)
        {
            _message = message;
        }

    }
}

Usage:



    class Program
    {
        static void Main(string[] args)
        {
            MessageManager msg = new MessageManager(new Sms());
            msg.Sms.Get();
            msg.Sms.Send();
            Console.Read();
        }
    }

Usage2


namespace DependencyInjection
{

    public interface IMessage
    {
        public  void Get();
        public  void Send();
    }


    public class Sms :  IMessage
    {
        public  void IMessage.Get()
        {
            Console.WriteLine("Message Get!");
        }
        public  void IMessage.Send()
        {
            Console.WriteLine("Message Send!");
        }
    }

    public class MessageManager
    {
        private IMessage _message;

        public Sms Sms
        {
            get { return _message as Sms; }
            set { _message = value; }
        }

        public MessageManager(IMessage message)
        {
            _message = message;
        }

    }
}

What is the difference between Usage1 and usage2? When do I choose usage1 or Usage2?

like image 291
loki Avatar asked Nov 18 '12 16:11

loki


People also ask

When should you use abstract class vs interface?

Abstract classes should be used primarily for objects that are closely related, whereas interfaces are best suited for providing common functionality to unrelated classes. If you are designing small, concise bits of functionality, use interfaces. If you are designing large functional units, use an abstract class.

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. Save this answer.

Is interface necessary for dependency injection?

You can skip the interface role and inject the service object directly into the client. But by doing that, you break with the dependency inversion principle and your client has an explicit dependency on the service class. In some situations, this might be ok.

In which of these situations are interfaces 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.


3 Answers

Abstract classes here to fight with duplicated code. Interfaces - to define contracts (API).

Depend on interfaces - they simply describe contract (API) of dependency, and they can by mocked easily. So, start with interface:

public interface IMessage
{
    void Get(); // modifiers like public are not allowed here
    void Send();
}

And here is your dependent class, which should depend only on abstraction (i.e. interface):

public class MessageManager
{
    private IMessage _message;

    // depend only on abstraction 
    // no references to interface implementations should be here
    public IMessage Message
    {
        get { return _message; }
        set { _message = value; }
    }

    public MessageManager(IMessage message)
    {
        _message = message;
    }
}

Then create class, which will implement your interface:

public class Sms : IMessage
{
    // do not use explicit implementation 
    // unless you need to have methods with same signature
    // or you want to hide interface implementation
    public void Get()
    {
        Console.WriteLine("Message Get!");
    }

    public void Send()
    {
        Console.WriteLine("Message Send!");
    }
}

Now you have inversed dependencies - MessageManager and Sms depend only on IMessage. You can inject any IMessage implementations to MessageManager (MessageManager now fit OCP - open for extension, but closed for modification).

Create base abstract message class only when you have duplicated code in several IMessage implementors. When you create abstract class (place, where you move duplicated code), you should not change interface, because contract stays the same. Just inherit your base class from original IMessage interface.

like image 131
Sergey Berezovskiy Avatar answered Sep 28 '22 06:09

Sergey Berezovskiy


The original definition of an interface is an abstract class with all pure virtual methods (i.e. abstract methods), this was how you describe an interface in C++. If you are not creating virtual functions with default definitions then you really do not need an abstract class at all. If you do have some default functionality that you would like the children of your Message class to inherit (and allow to override or not) then you would use an abstract class. An abstract class can also define protected methods and/or properties and fields, these can be used by classes that inherit from the abstract class but not by classes that use the abstract class. All methods in an interface would be public. In the case you laid out an interface would be fine.

like image 20
nerdybeardo Avatar answered Sep 28 '22 06:09

nerdybeardo


based on what I see you aren't really using an interface at all. Sure you implement the methods, but the consuming class shouldn't really know or even care about the implementation. Therefore, you shouldn't really see any reference or casting to Sms. You should be using a IoC framework such as Unity, Ninject, structuremap. If you actually need a public property returning an IMessage, it should return IMessage and not Sms, whether you should be doing that is a different conversation.

That said, the first Usage doesn't have anything in the IMessage so it is worthless. Also, I often use an abstract / base class to handle common functionality between multiple implementations of an interface. In you scenario, there is no need for the abstract class. The only time I create abstract methods without any code is if the abstract class actually fires that method in some capacity but expects the derived class to implement the functionality.

Anyway, to answer you question Usage #2 seems closer to the correct solution, but just remove the references to Sms and let an IoC container handle that.

like image 42
Rob Allen Avatar answered Sep 28 '22 07:09

Rob Allen