una que programacion polimorfismo metodos llamar instanciar herencia ejemplos clases clase abstracta c# inheritance function-overriding

que - polimorfismo c#



Forzar a llamar al método base desde fuera de una clase derivada (7)

Tengo dos clases:

public class MyBase { public virtual void DoMe() { } } public class MyDerived:MyBase { public override void DoMe() { throw new NotImplementedException(); } }

Y tengo el siguiente código para crear una instancia MyDerived:

MyDerived myDerived=new MyDerived();

¿El problema es cómo llamar a DoMe de la clase base? Si utilizo myDerived.DoMe (), se invocará el método derivado, dando como resultado una excepción. Traté de transmitir myDerived a MyBase, sin embargo, sigue siendo la versión derivada del método que se llama.

Editar: como se menciona en el siguiente comentario, no puedo cambiar eitehr MyDerived o MyBase porque no son mi código.


La clase derivada no necesita proporcionar una implementación del método. Quítelo y la implementación en la clase base se llamará por defecto.

Si, a diferencia de su ejemplo, el método en la clase base es abstracto y debe proporcionar una implementación, pero no tiene sentido que la clase derivada proporcione uno, probablemente haya un problema con el diseño de las clases.


No puedes llamar a la versión de clase base.

Si el método no funciona en la clase derivada, entonces es bastante improbable que la versión base del método funcione cuando se invoca en una instancia de la clase derivada. Eso es solo pedir problemas. La clase no fue diseñada para funcionar de esa manera, y lo que estás tratando de hacer probablemente solo cause que otras partes de la clase se comporten de manera impredecible.

¿Por qué necesita llamar a este método en el objeto cuando el objeto le dice directamente que no funcionará?

Me parece que estas clases tienen algunos defectos de diseño, y si no puedes cambiar las clases, quizás puedas cambiar a una biblioteca más bien diseñada.


Para llamar a MyBase.DoMe () desde una clase externa necesitaría una instancia de MyBase o una instancia derivada que no anule DoMe (). Se llamará a un método declarado como virtual en el tipo de tiempo de ejecución real del objeto, no el tipo de objeto, que es el motivo por el que el envío a MyBase no cambia el método que se llama. Sin embargo, si el método no se declaró en MyBase como virtual y MyDerived aún se implementó DoMe (), estaría "ocultando" la implementación de MyBase. Por lo tanto, si la referencia era MyDerived, llamaría a MyDerived.DoMe (), pero en este caso se convertiría a MyBase myBase = (MyBase) myDerived y luego a llamar a myBase.DoMe () llamaría a MyBase.DoMe ().


public class MyDerived:MyBase{ public override void DoMe() { base.DoMe(); } }

EDITAR:

No puede acceder al método de clases base desde "afuera" sin pasar por el método de subclases. Su única opción es instanciar su clase base directamente y llamar a su método.

MyBase mb = new MyBase(); mb.DoMe();


Dadas sus restricciones, existe otra posibilidad:

Descargar .Net Reflector. Descompile el código existente y luego realice los cambios que necesite para respaldar su situación.

Por supuesto, revise la legalidad de esto antes de continuar.


Hay una solución, pero es fea: utilice la reflexión para obtener el método de clase base, y luego emita el IL necesario para llamarlo. Echa un vistazo a esta publicación de blog que ilustra cómo hacerlo. He utilizado este enfoque con éxito para llamar a la implementación de un método de la clase base cuando todo lo que tengo es una referencia a una clase derivada que anula ese método.


Esta pregunta es muy antigua, pero no veo la siguiente opción:

Puede usar la palabra clave ''nueva'' para especificar métodos superpuestos. Entonces simplemente lanzarías a la clase cuyo método deseas llamar.

public class MyBase { public virtual void DoMe() { } } public class MyDerived:MyBase { //note the use of ''new'' and not ''override'' public new void DoMe() { throw new NotImplementedException(); } }

Implementación

var myDerived = new MyDerived(); var derivedDoMe = myDerived.DoMe(); var baseDoMe = ((MyBase)myDerived).DoMe();