// Cannot change source code
class Base
{
public virtual void Say()
{
Console.WriteLine("Called from Base.");
}
}
// Cannot change source code
class Derived : Base
{
public override void Say()
{
Console.WriteLine("Called from Derived.");
base.Say();
}
}
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
class Program
{
static void Main(string[] args)
{
SpecialDerived sd = new SpecialDerived();
sd.Say();
}
}
El resultado es:
Llamado de Derivado Especial.
Llamado de derivado. / * esto no se espera * /
Llamado desde la base.
¿Cómo puedo reescribir la clase SpecialDerived para que no se invoque el método "Derivado" de la clase media?
ACTUALIZACIÓN:
La razón por la que quiero heredar de Derived en lugar de Base es que la clase Derived contiene muchas otras implementaciones. Como no puedo hacer base.base.method()
aquí, supongo que la mejor manera es hacer lo siguiente.
// No se puede cambiar el código fuente
class Derived : Base
{
public override void Say()
{
CustomSay();
base.Say();
}
protected virtual void CustomSay()
{
Console.WriteLine("Called from Derived.");
}
}
class SpecialDerived : Derived
{
/*
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
*/
protected override void CustomSay()
{
Console.WriteLine("Called from Special Derived.");
}
}
c#
polymorphism
ARIZONA.
fuente
fuente
Respuestas:
Solo quiero agregar esto aquí, ya que las personas aún vuelven a esta pregunta incluso después de mucho tiempo. Por supuesto, es una mala práctica, pero aún es posible (en principio) hacer lo que el autor quiere con:
fuente
Func<stuff>
lugar deAction
Esta es una mala práctica de programación y no está permitida en C #. Es una mala práctica de programación porque
Los detalles de la base son detalles de implementación de la base; no deberías depender de ellos. La clase base está proporcionando una abstracción de la gran base; deberías usar esa abstracción, no construir un bypass para evitarlo.
Para ilustrar un ejemplo específico del punto anterior: si se permite, este patrón sería otra forma de hacer que el código sea susceptible a fallas de clase frágil. Supongamos que
C
deriva de loB
que derivaA
. Código enC
usosbase.base
para llamar a un método deA
. Luego, el autor seB
da cuenta de que han puesto demasiado equipo en la claseB
, y un mejor enfoque es hacer una clase intermediaB2
que se deriveA
y seB
derive deB2
. Después de ese cambio, el código inC
invoca un método enB2
, no enA
, porqueC
el autor asumió que la implementación detallaB
, es decir, que su clase base directa esA
, nunca cambiaría Muchas decisiones de diseño en C # son para mitigar la probabilidad de varios tipos de fallas de base frágil; la decisión de hacerbase.base
ilegal evita por completo este sabor particular de ese patrón de falla.Derivó de su base porque le gusta lo que hace y quiere reutilizarlo y extenderlo. Si no le gusta lo que hace y quiere solucionarlo en lugar de trabajar con él, ¿por qué se derivó de él en primer lugar? Derive usted mismo de la base de datos si esa es la funcionalidad que desea usar y ampliar.
La base puede requerir ciertos invariantes por razones de seguridad o de consistencia semántica que se mantienen con los detalles de cómo la base usa los métodos de la base. Permitir que una clase derivada de la base omita el código que mantiene esos invariantes podría poner a la base en un estado inconsistente y corrupto.
fuente
No puedes desde C #. Desde IL, esto es realmente compatible. Puedes hacer una llamada no virtuosa a cualquiera de tus clases para padres ... pero no lo hagas. :)
fuente
La respuesta (que sé que no es lo que estás buscando) es:
La verdad es que solo tienes interacción directa con la clase de la que heredas. Piense en esa clase como una capa, proporcionando tanto o tan poca o la funcionalidad de su padre como lo desee a sus clases derivadas.
EDITAR:
Tu edición funciona, pero creo que usaría algo como esto:
Por supuesto, en una implementación real, puede hacer algo más como esto para ampliar y mantener:
Luego, las clases derivadas pueden controlar el estado de sus padres de manera apropiada.
fuente
Derived
que se llamaBase.Say
, para que se pueda llamarSpecialDerived
? Más simple, no?¿Por qué no simplemente convertir la clase secundaria en una clase primaria específica e invocar la implementación específica entonces? Esta es una situación de caso especial y se debe utilizar una solución de caso especial. Sin
new
embargo , tendrá que usar la palabra clave en los métodos secundarios.fuente
fuente
También puede hacer una función simple en la clase derivada de primer nivel, para llamar a la función de base grande
fuente
Mi 2c para esto es implementar la funcionalidad que necesita para ser llamado en una clase de kit de herramientas y llamarlo desde donde lo necesite:
Esto requiere cierta reflexión sobre el privilegio de acceso, es posible que deba agregar algunos
internal
métodos de acceso para facilitar la funcionalidad.fuente
En los casos en que no tenga acceso a la fuente de la clase derivada, pero necesite toda la fuente de la clase derivada además del método actual, le recomendaría que también haga una clase derivada y llame a la implementación de la clase derivada.
Aquí hay un ejemplo:
fuente
Como se puede ver en publicaciones anteriores, uno puede argumentar que si la funcionalidad de la clase necesita ser burlada, entonces algo está mal en la arquitectura de la clase. Eso puede ser cierto, pero no siempre se puede reestructurar o refactorizar la estructura de clases en un proyecto grande y maduro. Los diversos niveles de gestión de cambios pueden ser un problema, pero mantener la funcionalidad existente funcionando igual después de la refactorización no siempre es una tarea trivial, especialmente si se aplican restricciones de tiempo. En un proyecto maduro, puede ser una tarea difícil evitar que pasen varias pruebas de regresión después de una reestructuración del código; a menudo hay "rarezas" oscuras que aparecen. Tuvimos un problema similar en algunos casos, la funcionalidad heredada no debería ejecutarse (o debería realizar otra cosa). El enfoque que seguimos a continuación, fue poner el código base que debe excluirse en una función virtual separada. Esta función puede ser anulada en la clase derivada y la funcionalidad excluida o alterada. En este ejemplo, se puede evitar que "Texto 2" salga en la clase derivada.
fuente
Parece que hay muchas de estas preguntas que rodean la herencia de un método miembro de una clase de abuelo, anulándolo en una segunda clase y luego llamando a su método nuevamente de una clase de nieto. ¿Por qué no simplemente heredar los miembros de los abuelos hasta los nietos?
Parece simple ... el nieto hereda el método de los abuelos aquí. Piénselo ... así es como "Object" y sus miembros como ToString () se heredan en todas las clases en C #. Creo que Microsoft no ha hecho un buen trabajo al explicar la herencia básica. Hay demasiado énfasis en el polimorfismo y la implementación. Cuando reviso su documentación no hay ejemplos de esta idea tan básica. :(
fuente
Si desea acceder a los datos de la clase base, debe usar "esta" palabra clave o usar esta palabra clave como referencia para la clase.
fuente