Dichiara la variabile come interfaccia

3

Quando dovrebbe o non dovrebbe essere dichiarata una variabile come tipo di interfaccia personalizzata?

Quando ho attraversato un po 'di codice, avevo bisogno di sapere cosa stava succedendo qui:

Public Class MyMainProject
    ....
    Public Sub DoMyWork()
        Dim objIMyInterface As IMyInterface
        ....
        objIMyInterface = GetReturnObject()
    End Sub
    ....
End Class

In base a ciò che ho visto, objIMyInterface viene utilizzato solo per una cosa. Non sapevo quante classi implement , ma non ci sono casting di tipi simili in questo codice. objIMyInterface è usato proprio come un tipo normale, non anonimo in meno. In secondo luogo, la mia ricerca ha aiutato un po '...

GetReturnObject succede per restituire un'istanza di IMyInterface . L'oggetto di ritorno di GetReturnObject , ovviamente, ha una chiamata a un altro metodo.

Public Function GetReturnObject() As IMyInterface
    Dim retObject As IMyInterface
    ...
            retObject = AnotherMethod()
    ...
    Return retObject
End Function

Quindi provo ad entrare in AnotherMethod , ma è in un progetto senza simboli. Quindi dopo alcune ricerche, trovo la fonte e la analizzo. Dopo aver ripetuto questo processo alcune volte, alla fine ottengo qualcosa di simile:

Public Function FinalMethod() As IMyInterface
    Dim FinalObject As MyClassType
    ...
            FinalObject = GetMyClassType()
    ...
    Return FinalObject 
End Function

Yay! GetMyClassType restituisce MyClassType ! Vado in quella classe e ovviamente:

Public Class MyClassType
    Implements IMyInterface
    ...
End Class

Quello che finisco per scoprire è che IMyInterface è usato da nient'altro che questa classe. No biggie, è tutto un buon codice dal suo aspetto. Ma poi torno al mio progetto originale, me ne accorgo:

Public Class MyMainProject
    ....
    Public Sub DoMyWork()
        Dim objIMyInterface As IMyInterface
        ....
        objIMyInterface = GetReturnObject()
    End Sub
    ....
    Public Sub OtherWork()
        Dim objMyType As MyClassType
        ....
    End Sub
    ....
End Class

Il tizio che l'ha creato è da tempo scomparso, ma mi piacerebbe sapere quali sono i tuoi pensieri su quale metodo utilizzare. Devo dichiarare entrambi come IMyInterface ? O entrambi come MyClassType ? Il codice funziona bene in ogni caso.

    
posta Suamere 13.06.2013 - 22:57
fonte

3 risposte

2

Per un'interfaccia con una singola classe di implementazione, l'utilizzo dell'interfaccia e della classe concreta in una classe di consumo è errato A MENO CHE l'interfaccia non includa tutte le proprietà / metodi della classe concreta.

Scegli uno o l'altro e, a meno che non sia necessario / utile per il test o esponga solo un sottoinsieme della funzionalità della classe, rilascia l'interfaccia.

E non solo in questa classe, ovunque. Un'interfaccia viene utilizzata per astrarre proprietà / metodi da una classe concreta, consentendo l'uso di più classi in modo intercambiabile. Se non ci sono altre classi, e non c'è probabilmente cappuccio di altre classi, allora un'interfaccia è un'astrazione superflua. Le astrazioni non necessarie dovrebbero essere evitate.

    
risposta data 15.06.2013 - 05:58
fonte
2

Normalmente, dichiareresti un tipo di interfaccia di ritorno solo se non eri assolutamente sicuro del tipo che avresti ottenuto, ma sapevi che qualunque tipo tornasse, sicuramente implementerebbe sicuramente quell'interfaccia.

Ad esempio ...

public Interface IMammal()
{
    public void Breastfeed();
}

public class Cat : IMammal()
{
    public void Breastfeed()
    {
        // stuff happens here
    }

    public bool Killsmice()
    {
        return true;
    }
}

public class Elephant : IMammal
{
    public void Breastfeed()
    {
        // stuff
    }

    public bool HasTrunk()
    {
        return true;
    }
}

Ora, diamo un'occhiata a quando potrebbe essere utile.

public class Zoo
{
    public void AnimalType(IMammal mammal)
    {
        // here, the Breastfeed method could safely be called, but the HasTrunk or
        // KillsMice methods (they're methods because they are neither get nor set)
        // cannot safely be called. All this method knows is that it's getting a
        // class which implements IMammal
    }
}

Nel tuo caso, hai un'interfaccia che solo si applica a una singola classe. A condizione che non creerai mai un'altra classe che implementa l'interfaccia, è meglio creare un'istanza della classe effettiva - il tuo codice sarà più leggibile.

    
risposta data 13.06.2013 - 23:42
fonte
1

Forse il programmatore che ha creato l'interfaccia ha pensato che sarebbe stata un'astrazione che avrebbe ottenuto un certo riutilizzo (più implementazioni) da qualche parte nel futuro (YAGNI, tuttavia, è meglio attendere il riutilizzo e quindi il refactoring delle astrazioni).

Poteva aver creato l'interfaccia in modo da poter creare oggetti finti intorno ad esso da utilizzare nei test unitari. La creazione di interfacce puramente a scopo di test è controversa per alcuni (inizialmente era per me).

Le interfacce a volte sono utili per formulare chiamate e richieste dal punto di vista del chiamante. Anche se c'è solo un'implementazione che può rispondere, può comunque essere utile semanticamente o concettualmente. Può anche proteggere l'interfaccia pubblica della classe di implementazione, forse utilizzata da altre prospettive.

    
risposta data 15.06.2013 - 04:14
fonte

Leggi altre domande sui tag