Ha senso definire un'interfaccia se ho già una classe astratta?

12

Ho una classe con alcune funzionalità predefinite / condivise. Io uso abstract class per questo:

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

Come puoi vedere, ho anche l'interfaccia ITypeNameMapper . Ha senso definire questa interfaccia se ho già una classe astratta TypeNameMapper o abstract class è sufficiente?

TypeDefinition in questo esempio minimale è anch'esso astratto.

    
posta Konrad 26.07.2018 - 15:17
fonte

5 risposte

31

Sì, perché C # non consente l'ereditarietà multipla tranne che con le interfacce.

Quindi se ho una classe che sia sia TypeNameMapper che SomethingelseMapper posso fare:

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); }
}
    
risposta data 26.07.2018 - 15:23
fonte
1

Le interfacce e le classi astratte hanno scopi diversi:

  • Interfacce definiscono le API e appartengono ai client e non alle implementazioni.
  • Se le classi condividono le implementazioni, puoi trarre vantaggio da una classe astratta .

Nel tuo esempio, interface ITypeNameMapper definisce le esigenze dei clienti e abstract class TypeNameMapper non aggiunge alcun valore.

    
risposta data 27.07.2018 - 01:15
fonte
0

L'intero concetto di interfacce è stato creato per supportare una famiglia di classi con un'API condivisa.

Questo dice esplicitamente che qualsiasi uso di un'interfaccia implica che ci sia (o ci si aspetta che sia) più di un'implementazione delle sue specifiche.

I quadri DI hanno intorbidato le acque qui in quanto molti di loro richiedono un'interfaccia anche se ci sarà sempre solo un'implementazione - per me questo è un sovraccarico irragionevole per quello che nella maggior parte dei casi è solo un modo più complesso e più lento di chiamare nuove , ma è quello che è.

La risposta sta nella domanda stessa. Se hai una classe astratta, ti stai preparando per la creazione di più di una classe derivata con un'API comune. Pertanto, l'uso di un'interfaccia è chiaramente indicato.

    
risposta data 26.07.2018 - 19:56
fonte
0

Se vogliamo rispondere esplicitamente alla domanda, l'autore dice "Ha senso definire questa interfaccia se ho già una classe astratta TypeNameMapper o la classe astratta è sufficiente?"

La risposta è sì e no - Sì, dovresti creare l'interfaccia anche se hai già la classe base astratta (perché non dovresti riferirti alla classe base astratta in nessun codice client), e no, perché dovresti non ho creato la classe base astratta in assenza di un'interfaccia.

Il fatto di non aver riflettuto abbastanza sull'API che stai cercando di costruire è evidente. Prepara prima l'API, quindi fornisci un'implementazione parziale se lo desideri. Il fatto che la tua classe base astratta digiti il check in code è sufficiente per dirti che non è l'astrazione giusta.

Come nella maggior parte delle cose in OOD, quando sei nel groove e fai fare bene il modello a oggetti, il tuo codice ti informerà su cosa verrà dopo. Inizia con un'interfaccia, implementa quell'interfaccia nelle classi che ti servono. Se ti ritrovi a scrivere codice simile, estrailo in una classe base astratta - è l'interfaccia che è importante, la classe base astratta è solo un aiuto e ce ne possono essere più di una.

    
risposta data 05.08.2018 - 23:11
fonte
-1

È piuttosto difficile rispondere senza conoscere il resto dell'applicazione.

Supponendo che tu stia usando una specie di modello DI e hai progettato il tuo codice per essere il più estendibile possibile (in modo che tu possa aggiungere nuovo TypeNameMapper facilmente) direi di sì.

Motivi per:

  • Lo ottieni gratuitamente gratuitamente, poiché la classe base implementa interface che non devi preoccuparti di esso in eventuali implementazioni secondarie
  • La maggior parte dei framework IoC e delle librerie di Mocking si aspetta interface s. Mentre molti di loro lavorano con classi astratte non è sempre un dato di fatto e io sono un grande sostenitore nel seguire lo stesso percorso dell'altro 99% degli utenti di una biblioteca, ove possibile.

Ragioni contrarie:

  • In senso stretto (come hai sottolineato) non hai VERAMENTE bisogno di
  • Se la class / interface cambia, c'è un piccolo overhead aggiuntivo

Tutto sommato direi che dovresti creare il interface . I motivi contrari sono abbastanza trascurabili ma, sebbene sia possibile utilizzare gli abstract in mocking e IoC, spesso è molto più semplice con le interfacce. In definitiva, però, non avrei criticato il codice di un collega se fossero andati dall'altra parte.

    
risposta data 26.07.2018 - 15:24
fonte

Leggi altre domande sui tag