web-dev-qa-db-fra.com

Est-il judicieux de définir une interface si j'ai déjà une classe abstraite?

J'ai une classe avec des fonctionnalités par défaut/partagées. J'utilise abstract class pour ça:

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);
}

Comme vous pouvez le voir, j'ai également l'interface ITypeNameMapper. Est-il judicieux de définir cette interface si j'ai déjà une classe abstraite TypeNameMapper ou abstract class suffit-il?

TypeDefinition dans cet exemple minimal est également abstrait.

12
Konrad

Oui, car C # ne permet pas l'héritage multiple sauf avec les interfaces.

Donc, si j'ai une classe qui est à la fois un TypeNameMapper et SomethingelseMapper, je peux faire:

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); }
}
31
Ewan

Les interfaces et les classes abstraites ont différentes fonctions:

  • Interfaces définissez les API et appartiennent aux clients et non aux implémentations.
  • Si les classes partagent des implémentations, vous pouvez bénéficier d'une classe abstract.

Dans votre exemple, interface ITypeNameMapper définit les besoins des clients et abstract class TypeNameMapper n'ajoute aucune valeur.

1
Geoffrey Hale

Si nous voulons répondre explicitement à la question, l'auteur dit "Est-il judicieux de définir cette interface si j'ai déjà une classe abstraite TypeNameMapper ou une classe abstraite est juste suffisante?"

La réponse est oui et non - Oui, vous devez créer l'interface même si vous avez déjà la classe de base abstraite (car vous ne devez pas faire référence à la classe de base abstraite dans aucun code client), et non, car vous ne devriez pas avoir créé la classe de base abstraite en l'absence d'une interface.

Le fait que vous n'ayez pas suffisamment réfléchi à l'API que vous essayez de créer est évident. Proposez d'abord l'API, puis fournissez une implémentation partielle si vous le souhaitez. Le fait que votre classe de base abstraite saisisse du code dans le code suffit pour vous dire que ce n'est pas la bonne abstraction.

Comme dans la plupart des choses dans OOD, lorsque vous êtes dans le groove et que votre modèle d'objet est bien fait, votre code vous informera de ce qui va suivre. Commencez avec une interface, implémentez cette interface dans les classes dont vous avez besoin. Si vous vous retrouvez en train d'écrire du code similaire, extrayez-le dans une classe de base abstraite - c'est l'interface qui est importante, la classe de base abstraite n'est qu'un assistant et il peut y en avoir plusieurs.

0
Rodney P. Barbati

L'ensemble du concept d'interfaces a été créé afin de prendre en charge une famille de classes ayant une API partagée.

Cela signifie explicitement que toute utilisation d'une interface implique qu'il existe (ou devrait exister) plusieurs implémentations de sa spécification.

Les cadres de DI ont brouillé les eaux ici dans la mesure où beaucoup d'entre eux nécessitent une interface même s'il n'y aura qu'une seule implémentation - pour moi, cela représente un surcoût déraisonnable pour ce qui, dans la plupart des cas, n'est qu'un moyen plus complexe et plus lent d'appeler le nouveau, mais il c'est ce que c'est.

La réponse réside dans la question elle-même. Si vous avez une classe abstraite, vous vous préparez à la création de plusieurs classes dérivées avec une API commune. Ainsi, l'utilisation d'une interface est clairement indiquée.

0
Rodney P. Barbati