virtuales que polimorfismo polimorfico metodos herencia form and abstractos c# oop

polimorfismo - ¿Por qué no puedo declarar que los métodos de C#son virtuales y estáticos?



que es override en c# (14)

Tengo una clase auxiliar que es solo un montón de métodos estáticos y me gustaría crear una subclase de la clase auxiliar. Algunos comportamientos son únicos dependiendo de la subclase, por lo que me gustaría llamar a un método virtual desde la clase base, pero como todos los métodos son estáticos, no puedo crear un método virtual simple (necesita referencia de objeto para acceder al método virtual).

¿Hay alguna forma de evitar esto? Creo que podría usar un singleton .. HelperClass.Instance.HelperMethod () no es mucho peor que HelperClass.HelperMethod (). Brownie señala a cualquiera que pueda señalar algunos idiomas que admiten métodos estáticos virtuales.

Editar: OK, sí, estoy loco. Los resultados de búsqueda de Google me hicieron pensar que no estaba allí por un tiempo.


De hecho, esto se puede hacer en Delphi. Un ejemplo:

type TForm1 = class(TForm) procedure FormShow(Sender: TObject); end; TTestClass = class public class procedure TestMethod(); virtual; end; TTestDerivedClass = class(TTestClass) public class procedure TestMethod(); override; end; TTestMetaClass = class of TTestClass; var Form1: TForm1; implementation {$R *.dfm} class procedure TTestClass.TestMethod(); begin Application.MessageBox(''base'', ''Message''); end; class procedure TTestDerivedClass.TestMethod(); begin Application.MessageBox(''descendant'', ''Message''); end; procedure TForm1.FormShow(Sender: TObject); var sample: TTestMetaClass; begin sample := TTestClass; sample.TestMethod; sample := TTestDerivedClass; sample.TestMethod; end;

Bastante interesante. Ya no uso Delphi, pero recuerdo haber sido capaz de crear muy fácilmente diferentes tipos de controles en un lienzo de diseñador personalizado usando la característica de metaclase: la clase de control, por ej. TButton, TTextBox, etc. era un parámetro, y podría llamar al constructor apropiado usando el argumento de la metaclase real.

Tipo de patrón de fábrica del hombre pobre :)


En realidad, es posible combinar virtual y estático para un método o miembro utilizando la palabra clave new lugar de virtual .

Aquí hay un ejemplo:

class Car { public static int TyreCount = 4; public virtual int GetTyreCount() { return TyreCount; } } class Tricar : Car { public static new int TyreCount = 3; public override int GetTyreCount() { return TyreCount; } } ... Car[] cc = new Car[] { new Tricar(), new Car() }; int t0 = cc[0].GetTyreCount(); // t0 == 3 int t1 = cc[1].GetTyreCount(); // t1 == 4

Obviamente, el valor de TyreCount podría haberse establecido en el método GetTyreCount anulado, pero esto evita duplicar el valor. Es posible obtener el valor tanto de la clase como de la instancia de la clase.

Ahora, ¿puede alguien encontrar un uso realmente inteligente de esa característica?


Escuché que Delphi apoya algo como esto. Parece que lo hace haciendo que las clases presenten instancias de metaclass.

No lo he visto funcionar, así que no estoy seguro de que funcione, o qué sentido tiene eso.

PD Por favor corrígeme si me equivoco, ya que no es mi dominio.


Hay una manera de forzar una herencia de métodos "abstractos estáticos" a partir de una clase genérica abstracta. Vea lo siguiente:

public abstract class Mother<T> where T : Mother<T>, new() { public abstract void DoSomething(); public static void Do() { (new T()).DoSomething(); } } public class ChildA : Mother<ChildA> { public override void DoSomething() { /* Your Code */ } } public class ChildB : Mother<ChildB> { public override void DoSomething() { /* Your Code */ } }

Ejemplo (usando la Madre anterior):

public class ChildA : Mother<ChildA> { public override void DoSomething() { Console.WriteLine("42"); } } public class ChildB : Mother<ChildB> { public override void DoSomething() { Console.WriteLine("12"); } } public class Program { static void Main() { ChildA.Do(); //42 ChildB.Do(); //12 Console.ReadKey(); } }

No es tan bueno, ya que puede heredar de una sola clase abstracta y le pedirá que sea indulgente con su nueva implementación ().

Más, creo que será costoso para la memoria dependiendo del tamaño de tus clases heredadas. En caso de que tengas problemas de memoria, deberías establecer cada propiedad / variable después de la nueva en un método público, que es una forma horrible de tener valores predeterminados.


Mart lo hizo bien con la palabra clave ''nueva''. De hecho, llegué aquí porque necesitaba este tipo de funcionalidad y la solución de Mart funciona bien. De hecho, lo tomé uno mejor y convertí mi método de clase base en abstracto para obligar al programador a suministrar este campo.

Mi escenario fue el siguiente:

Tengo una clase base HouseDeed. Cada tipo de Casa se deriva de HouseDeed debe tener un precio.

Aquí está la clase parcial de HouseDeed:

public abstract class HouseDeed : Item { public static int m_price = 0; public abstract int Price { get; } /* more impl here */ }

Ahora veamos dos tipos de casas derivadas:

public class FieldStoneHouseDeed : HouseDeed { public static new int m_price = 43800; public override int Price { get { return m_price; } } /* more impl here */ }

y...

public class SmallTowerDeed : HouseDeed { public static new int m_price = 88500; public override int Price { get { return m_price; } } /* more impl here */ }

Como puede ver, puedo acceder al precio de la casa a través del tipo SmallTowerDeed.m_price, y la instancia new SmallTowerDeed (). Price Y al ser abstracto, este mecanismo irrita al programador para que le proporcione un precio por cada nuevo tipo de casa derivada.

Alguien señaló cómo ''estático virtual'' y ''virtual'' están conceptualmente en desacuerdo entre sí. Estoy en desacuerdo. En este ejemplo, los métodos estáticos no necesitan acceso a los datos de la instancia, por lo que los requisitos que (1) el precio estén disponibles a través del TIPO solo, y que (2) se satisfaga el precio.


No creo que estés loco. Solo quiere usar lo que actualmente es imposible en .NET.

Su solicitud de método estático virtual tendría mucho sentido si hablamos de genéricos. Por ejemplo, mi solicitud futura para los diseñadores de CLR es permitirme escribir Intereface de esta manera:

public interface ISumable<T> { static T Add(T left, T right); }

y úsalo así:

public T Aggregate<T>(T left, T right) where T : ISumable<T> { return T.Add(left, right); }

Pero es imposible ahora, así que lo estoy haciendo así:

public static class Static<T> where T : new() { public static T Value = new T(); } public interface ISumable<T> { T Add(T left, T right); } public T Aggregate<T>(T left, T right) where T : ISumable<T>, new() { return Static<T>.Value.Add(left, right); }


Porque un método virtual utiliza el tipo definido del objeto instanciado para determinar qué implementación ejecutar (a diferencia del tipo declarado de la variable de referencia)

... y estático, por supuesto, se trata de no preocuparse si hay incluso una instancia instanciada de la clase en absoluto ...

Entonces estos son incompatibles.

En pocas palabras, si quiere cambiar el comportamiento en función de qué subclase es una instancia, entonces los métodos deberían haber sido métodos virtuales en la clase base, no métodos estáticos.

Pero, como ya tiene estos métodos estáticos, y ahora necesita reemplazarlos, puede resolver su problema de esta manera: agregue métodos de instancia virtual a la clase base que simplemente delegue a los métodos estáticos y luego anule esos métodos de envoltura de instancia virtual ( no los estáticos) en cada subclase derivada, según corresponda ...


Puede lograr el mismo efecto simplemente teniendo un método estático regular y luego sombrearlo con la new palabra clave

public class Base { //Other stuff public static void DoSomething() { Console.WriteLine("Base"); } } public class SomeClass : Base { public new static void DoSomething() { Console.WriteLine("SomeClass"); } } public class SomeOtherClass : Base { }

Entonces puedes llamar a los métodos como si

Base.DoSomething(); //Base SomeClass.DoSomething(); //SomeClass SomeOtherClass.DoSomething(); //Base


Puedes usar la nueva palabra clave

namespace AspDotNetStorefront { // This Class is need to override StudioOnlineCommonHelper Methods in a branch public class StudioOnlineCommonHelper : StudioOnlineCore.StudioOnlineCommonHelper { // public static new void DoBusinessRulesChecks(Page page) { StudioOnlineCore.StudioOnlineCommonHelper.DoBusinessRulesChecks(page); } } }



Un método de sustitución proporciona una nueva implementación de un miembro que se hereda de una clase base. El método que se anula mediante una declaración de anulación se conoce como el método base anulado. El método base anulado debe tener la misma firma que el método de anulación. No puede anular un método no virtual o estático. El método básico anulado debe ser virtual, abstracto o anular.

Una declaración de invalidación no puede cambiar la accesibilidad del método virtual. Tanto el método de anulación como el método virtual deben tener el mismo modificador de nivel de acceso.

No puede usar los modificadores nuevos, estáticos o virtuales para modificar un método de sustitución.

Una declaración de propiedad primordial debe especificar exactamente el mismo modificador, tipo y nombre de acceso como la propiedad heredada, y la propiedad reemplazada debe ser virtual, abstracta o anular.


Vengo de Delphi y esta es una característica entre muchas que echo de menos en c #. Delphi le permitiría crear referencias de tipos escritos y podría pasar el tipo de una clase derivada donde sea que se necesite el tipo de clase principal. Este tratamiento de tipos como objetos tenía una poderosa utilidad. En particular, permite la determinación del tiempo de ejecución de metadatos. Estoy mezclando horriblemente la sintaxis aquí, pero en c # se vería algo así como:

class Root { public static virtual string TestMethod() {return "Root"; } } TRootClass = class of TRoot; // Here is the typed type declaration class Derived : Root { public static overide string TestMethod(){ return "derived"; } } class Test { public static string Run(){ TRootClass rc; rc = Root; Test(rc); rc = Derived(); Test(rc); } public static Test(TRootClass AClass){ string str = AClass.TestMethod(); Console.WriteLine(str); } }

produciría: raíz derivada


existe un método estático fuera de una instancia de una clase. No puede usar ningún dato no estático.

un método virtual será "sobreescrito" por una función sobrecargada dependiendo del tipo de una instancia.

entonces tienes una clara contradicción entre estático y virtual.

Esto no es un problema de apoyo, es un concepto.

Actualización: se demostró que estaba equivocado aquí (ver comentarios):

Así que dudo que encuentre ningún OOP-Language que admita métodos estáticos virtuales.


Los métodos estáticos virtuales no tienen sentido. Si llamo a HelperClass.HelperMethod(); , ¿por qué esperaría que se llamara algún método de subclase aleatoria? La solución realmente se descompone cuando tienes 2 subclases de HelperClass : ¿cuál HelperClass ?

Si desea tener métodos de tipo estático anulables, probablemente debería ir con:

  • Un singleton, si desea que la misma subclase se use globalmente.
  • Una jerarquía de clase de tradición, con una inyección de fábrica o de dependencia, si desea un comportamiento diferente en diferentes partes de su aplicación.

Elija la solución que tenga más sentido en su situación.