2012-09-07 7 views
13

Ho un'interfaccia con diversi metodi al suo interno.Esecuzione del metodo di override dichiarata in un'interfaccia

interface IMyInterface 
{ 
    //... 
    void OnItemClicked() 
    //... 
} 

E un'implementazione

class MyClass : IMyInterface 
{ 
    //Other methods 
    public void OnItemClicked(){ /*...*/ } 
} 

Ora, voglio avere una classe che si comporta come MyClass ad eccezione di OnItemClicked(), voglio alcune modifiche per questo metodo.

ho pensato di ereditare un override, ma io non voglio cambiare il MyClass (come: pubblico virtual vuoto OnItemClicked() ...) perché la sua non la mia realizzazione,

non voglio per implementare IMyInterface nuovamente perché OnItemClicked() è l'unica parte di MyClass da modificare.

Ho altro modo per farlo?

+0

Creare una classe intermedia tra questi due. –

risposta

15

Poiché si sta implementando un'interfaccia, il polimorfismo è probabilmente qualcosa che si desidera conservare. È impossibile sovrascrivere il metodo senza modificare la classe base con un virtuale, quindi è necessario utilizzare nuovo anziché virtuale come scritto da Tigran.

Ciò significa che scrivere questo tipo di codice, ma solo la versione base del metodo sarebbe eseguita:

List<MyClass> aList = new List<MyClass>(); 
aList.Add(new MyClass()); 
aList.Add(new MyNewClass()); 
foreach (MyClass anItem in aList) 
    anItem.OnItemClicked(); 

Per eseguire il codice giusto si dovrebbe scrivere brutto codice come questo:

List<MyClass> aList = new List<MyClass>(); 
aList.Add(new MyClass()); 
aList.Add(new MyNewClass()); 
foreach (MyClass anItem in aList) 
{ 
    MyNewClass castItem = anItem as MyNewClass; 
    if (castItem != null) 
     castItem.OnItemClicked(); 
    else 
     anItem.OnItemClicked(); 
} 

Ad ogni modo è possibile che le classi eseguano il metodo corretto quando vengono assegnate a variabili dichiarate come IMyInterface. La strada da percorrere è implementare esplicitamente la parte dell'interfaccia che si desidera sovrascrivere, nel caso specifico il metodo OnItemClicked.Il codice è il seguente:

public class MyNewClass : MyClass, IMyInterface // you MUST explicitly say that your class implements the interface, even if it's derived from MyClass 
{ 
    public new void OnItemClicked() //NEW keyword here you have the overridden stuff 
    { 
     /*...*/ 
    } 

    void IMyInterface.OnItemClicked() // No need for public here (all interfaces's methods must be public) 
    { 
     this.OnItemClicked(); 
    } 
} 

In questo modo:

MyClass cl = new MyNewClass(); 
cl.OnItemClicked(); 

esegue il metodo di base

MyNewClass cl = new MyNewClass(); 
cl.OnItemClicked(); 

esegue il metodo della classe derivata

IMyInterface cl = new MyNewClass(); 
cl.OnItemClicked(); 

esegue il metodo del deri ved classe ed è associato a runtime. Ciò significa che è possibile scrivere il codice del mio esempio iniziale in questo modo e avere i giusti metodi eseguiti:

List<IMyInterface> aList = new List<IMyInterface>(); 
aList.Add(new MyClass()); 
aList.Add(new MyNewClass()); 
foreach (IMyInterface anItem in aList) 
    anItem.OnItemClicked(); 
5

è possibile derivare da MyClass

public class MyNewClass : MyClass 
{ 
    public new void OnItemClicked(){ /*...*/ } //NEW keyword 
} 

L'unica cosa, prestare attenzione che in questo modo non si Supprot polimorfismo.

Per essere più chiari:

 MyClass cl = new MyNewClass(); 
    cl. MyMethod(); 

questo chiamerà MyClass metodo, anche se il tipo di oggetto reale è MyNewType. Per essere in grado di chiamare ciò che vogliamo, dobbiamo definire esplicitly tipo

 MyNewClass cl = new MyNewClass(); 
    cl. MyMethod(); //WILL CALL METHOD WE WANT 
+0

Ha menzionato nel suo post: ho pensato di ereditare un override ma non voglio modificare MyClass (come: public virtual void OnItemClicked() ...) perché non è la mia implementazione, –

+0

@ armen.shimoon: infatti non l'ha fatto. Dove vedi il codice che modifica l'implementazione di MyClass? – Tigran

+0

Il mio cattivo Tigran. Ho dato un'occhiata al codice e ho pensato che avessi "override" invece di "new". Domanda: quando MyNewClass viene utilizzato come istanza di "IMyInterface", quale metodo verrà chiamato? –

3

Il modo più semplice è quello di creare una nuova classe che imita "is-a" con "ha -a ":

public interface IMyInterface 
{ 
    void OnItemClicked(); 
    void OnItemHover(); 
    void OnItemDoubleClicked(); 
} 

public class MyNewClass : IMyInterface 
{ 
    private IMyInterface _target; 

    public MyNewClass(IMyInterface target) 
    { 
     _target = target; 
    } 

    public void OnItemClicked() 
    { 
     // custom functionality 
    } 

    public void OnItemHover() 
    { 
     _target.OnItemHover(); 
    } 

    public void OnItemDoubleClicked() 
    { 
     _target.OnItemDoubleClicked(); 
    } 
} 
+0

OK, ma non è possibile assegnarlo a una variabile MyClass –

+0

Sì, ma nella risposta in cui è possibile assegnarlo a una variabile MyClass e si è chiamato OnItemClicked() si eseguirebbe l'errore funzione. Supponevo che l'interfaccia fosse la parte importante, altrimenti non funzionerebbe correttamente, ma nemmeno l'altra risposta. –

+0

Hai ragione, infatti, preferisco la tua risposta all'altro, stavo solo indicando perché preferisco la mia risposta alla tua :-) –