2012-09-07 12 views
13

Tengo una interfaz con varios métodos.Sobrescribe la implementación del método declarada en una interfaz

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

Y una implementación

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

Ahora, yo quiero tener una clase que se comporta como MyClass excepción de OnItemClicked(), quiero algunas modificaciones de este método.

pensé para heredar una anulación pero no quieren cambiar el MyClass (como: public void virtual OnItemClicked() ...) porque no es mi aplicación,

no quiero para implementar IMyInterface nuevamente porque OnItemClicked() es la única parte de MyClass para modificar.

¿Tengo alguna otra forma de hacerlo?

+0

Cree una clase intermedia entre estos dos. –

Respuesta

15

Dado que está implementando una interfaz, es probable que el polimorfismo sea algo que le gustaría conservar. Es imposible anular el método sin modificar la clase base con una virtual, por lo que debe usar nueva en lugar de virtual como escribió Tigran.

Esto significa que la escritura de este tipo de código, pero sólo la versión base del método sería ejecutado:

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

Para ejecutar el código correcto que debe escribir código feo como este:

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

De todos modos hay una manera de que tus clases ejecuten el método correcto cuando se les asigna variables declaradas como IMyInterface. El camino a seguir es implementar explícitamente la parte de la interfaz que desea sobrescribir, en su caso el método OnItemClicked.El código es la siguiente:

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

De esta manera:

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

ejecuta el método de base

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

ejecuta el método de la clase derivada

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

ejecuta el método de la deri ved clase y está obligado en tiempo de ejecución. Esto significa que puede escribir el código de mi ejemplo inicial de esta manera y ejecutar los métodos correctos:

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

se puede derivar de MyClass

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

La única cosa, prestar atención a que de esta manera no Supprot polimorfismo.

Para ser más claro:

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

Para ello, será MyClass método, incluso si el tipo de objeto real de es MyNewType. Para ser capaz de llamar a lo que queremos, tenemos que definir esplicitly tipo

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

Mencionó en su post: Pensé en heredar una anulación, pero no quiero cambiar MyClass (como: vacío virtual público OnItemClicked() ...) porque no es mi implementación, –

+0

@ armen.shimoon: de hecho, él no lo hizo. ¿Dónde ves el código que cambia la implementación de MyClass? – Tigran

+0

Mi mal Tigran. Eché un vistazo al código y pensé que había "anulado" en lugar de "nuevo". Pregunta: cuando MyNewClass se usa como una instancia de "IMyInterface", ¿qué método se llamará? –

3

La forma más sencilla es crear una nueva clase que imita "es-un" uso "tiene -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, pero no puede asignar esto a una variable MyClass –

+0

Sí, pero en la respuesta donde puede asignarlo a una variable MyClass y llamó a OnItemClicked() se ejecutaría un error función. Asumía que la interfaz era la parte importante, de lo contrario, esto no funcionaría correctamente, pero tampoco la otra respondería. –

+0

Tienes razón, de hecho, prefiero tu respuesta a la otra, solo estaba señalando por qué prefiero mi respuesta a la tuya :-) –

Cuestiones relacionadas