2013-07-10 9 views
6

L'ereditarietà di una classe con metodi non utilizzati viola il principio di separazione dell'interfaccia?Principio di segregazione di ereditarietà e interfaccia

Ad esempio:

abstract class Base 
{ 
    public void Receive(int n) 
    { 
     // . . . (some important work) 

     OnMsg(n.ToString()); 
    } 

    protected abstract void OnMsg(string msg); 
} 

class Concrete : Base 
{ 
    protected override void OnMsg(string msg) 
    { 
     Console.WriteLine("Msg: " + msg); 
    } 
} 

Concrete dipende dal metodo di Base.Receive(int n), ma non è mai lo usa.

UPD

Definizione io uso:

ISP dichiara che nessun cliente dovrebbe essere costretto a dipendere da metodi che non utilizza.

+0

non sono sicuro che in questo esempio che non si usa, come sarebbe OnMsg mai essere chiamato se la ricezione non usato? – BlackICE

+0

Nel mio caso l'unico modo per chiamare 'OnMsg' è da' Ricevi'. Ho bisogno di questa ereditarietà per proiettare i dati in arrivo ('int n') sull'interfaccia di' Concrete' che usa 'string msg'. Nell'esempio reale c'è un lavoro più complesso del semplice 'ToString()' – astef

+0

@astef: come ha giustamente osservato Paulo, stai usando il 'modello di progettazione modello 'qui :) –

risposta

7

Penso che stai interpretando male ciò che dice il principio di separazione delle interfacce. Nel tuo caso stai bene e non stai "forzando" alcuna implementazione. In realtà si sta applicando il Template method design pattern

Se tu avessi un ipotetico

interface ICommunicateInt 
{ 
    int Receive(); 
    void Send(int n); 
} 

al fine di attuarla, la classe Base sarebbe stato costretto a implementare un metodo Send che non ha bisogno. Così, il provider di servizi Internet suggerisce che è meglio avere:

interface ISendInt 
{ 
    void Send(int n); 
} 

interface IReceiveInt 
{ 
    int Receive(); 
} 

in modo che le classi possono scegliere di implementare uno o entrambi. Anche i metodi di altre classi che hanno bisogno di una classe che può inviare un'Int, possono richiedere una

void Test(ISendInt snd) 
// void Test(ICommunicateInt snd) // Test would "force" snd to depend on 
            // a method that it does not use 
0

Non vedo che il calcestruzzo "dipende" da Base.Ricezione() nel modo in cui userei il termine. In che modo Concrete avrebbe bisogno di cambiare se la ricezione fosse modificata? Discuterei, non del tutto. Supponiamo di aver sostituito Receive() con un metodo con un nome diverso o con una firma diversa, concreto non sarebbe consapevole. Concrete chiama Receive()? No. Quindi non vedo alcuna dipendenza da Receive() qui.

La dipendenza è con la firma OnMsg(), Concrete partecipa in relazione molto particolare con Base, rispettando tale contratto OnMsg().

Ma in un altro senso Concrete dipende molto da Base.Receive(), che è l'interfaccia con il mondo esterno - senza quel metodo nessuno può accedere alle capacità di Concrete. In questo senso Concrete "usa" Base.Receive() ad un livello molto fondamentale.

+0

Ti capisco. Ma qual è la risposta? È un modo sbagliato di proiettare dati in entrata sconosciuti su un'interfaccia di destinazione? – astef

+0

No, non è male, è un modello fondamentalmente importante. – djna