13

I have a class with some default/shared functionality. I use abstract class for it:

public interface ITypeNameMapper
{
    string Map(TypeDefinition typeDefinition);
}

public abstract class TypeNameMapper : ITypeNameMapper
{
    public virtual string Map(TypeDefinition typeDefinition)
    {
        if (typeDefinition is ClassDefinition classDefinition)
        {
            return Map(classDefinition);
        }
        ...

        throw new ArgumentOutOfRangeException(nameof(typeDefinition));
    }

    protected abstract string Map(ClassDefinition classDefinition);
}

As you can see, I also have the interface ITypeNameMapper. Does it make sense to define this interface if I already have an abstract class TypeNameMapper or abstract class is just enough?

TypeDefinition in this minimal example is abstract too.

Deduplicator
  • 9,209
Konrad
  • 1,569

5 Answers5

32

Yes, because C# doesn't allow multiple inheritance except with interfaces.

So if I have a class which is both a TypeNameMapper and SomethingelseMapper I can do:

class MultiFunctionalClass : ITypeNameMapper, ISomethingelseMapper 
{
    private TypeNameMapper map1
    private SomethingelseMapper map2

    public string Map(TypeDefinition typeDefinition) { return map1.Map(typeDefintion);}

    public string Map(OtherDef otherDef) { return map2.Map(orderDef); }
}
Ewan
  • 83,178
1

Interfaces and abstract classes serve different purposes:

  • Interfaces define API's and belong to the clients not the implementations.
  • If classes share implementations then you may benefit from an abstract class.

In your example, interface ITypeNameMapper defines the needs of clients and abstract class TypeNameMapper is not adding any value.

0

The whole concept of interfaces was created in order to support a family of classes having a shared API.

This explicitly is saying that any use of an interface implies that there is (or is expected to be) more than one implementation of its specification.

DI frameworks have muddied the waters here in that many of them require an interface even though there will only ever be one implementation - to me this is unreasonable overhead for what in most cases is just a more complex and slower means of calling new, but it is what it is.

The answer lies in the question itself. If you have an abstract class, you are preparing for the creation of more than one derived class with a common API. Thus, the use of an interface is clearly indicated.

0

If we want to explicitly answer the question, author says "Does it make sense to define this interface if I already have an abstract class TypeNameMapper or abstract class is just enough?"

The answer is yes and no - Yes, you should create the interface even though you already have the abstract base class (because you should not be referring to the abstract base class in any client code), and no, because you should not have created the abstract base class in the absence of an interface.

That you haven't put enough thought into the API you are trying to build is evident. Come up with the API first, then provide a partial implementation if desired. The fact that your abstract base class does type checking in code is enough to tell you it isn't the right abstraction.

As in most things in OOD, when you are in the groove and have your object model done well, your code will inform you as to what comes next. Start with an interface, implement that interface in the classes you need it. If you find yourself writing similar code, extract it into an abstract base class - it it the interface that is important, the abstract base class is just a helper and there may be more than one.

-1

This is quite difficult to answer without knowing the rest of the application.

Assuming you're using some kind of DI model and have designed your code to be as extendable as possible (so you can add new TypeNameMapper easily) I would say yes.

Reasons for:

  • You effectively get it for free, as the base class implements the interface you don't need to worry about it in any child implementations
  • Most IoC frameworks and Mocking libraries expect interfaces. While many of them do work with abstract classes it's not always a given and I'm a big believer in following the same path as the other 99% of a library's users where possible.

Reasons against:

  • Strictly speaking (as you've pointed out) you don't REALLY need to
  • If the class/interface changes there's a little additional overhead

All things considered I would say that you should create the interface. The reasons against are fairly negligible but, while possible to use abstracts in mocking and IoC it's often far easier with interfaces. Ultimately though, I wouldn't criticise a colleague's code if they went the other way.

Deduplicator
  • 9,209
Liath
  • 3,436