2009-03-02 30 views
11

En C#, tengo Producto de clase base y Widget de clase derivada.C#: ¿Cómo puedo llamar a un método estático de una clase base desde un método estático de una clase derivada?

El producto contiene un método estático MyMethod().

Quiero llamar al método estático Product.MyMethod() desde el método estático Widget.MyMethod().

No puedo usar la palabra clave base, porque eso solo funciona con métodos de instancia.

Puedo llamar a Product.MyMethod() explícitamente, pero si más adelante cambio el widget para derivarlo de otra clase, tengo que revisar el método.

¿Hay alguna sintaxis en C# similar a la base que me permita llamar a un método estático de una clase base desde un método estático de una clase derivada?

+1

¿Alguna razón por la cual este método particular es estático? – Rad

Respuesta

16

static métodos son básicamente un método para retroceder desde conceptos orientados a objetos. Como consecuencia, no son muy flexibles en las jerarquías de herencia y no es posible hacer tal cosa directamente.

Lo más parecido que se me ocurre es una directiva using.

using mybaseclass = Namespace.BaseClass; 

class MyClass : mybaseclass { 

    static void MyMethod() { mybaseclass.BaseStaticMethod(); } 

} 
+4

> los métodos estáticos son básicamente un método para retroceder ... ¿Por qué es esto cierto? En el código de mi clase, los métodos que se basan en datos de instancia son métodos de instancia. Los métodos que no se basan en datos de instancia, sino que solo se basan en parámetros (si los hay) son métodos estáticos. Encuentro útil esta distinción. – MindModel

+0

Un método que no se basa en una instancia * object * no se reproduce según la mayoría de las reglas definidas para objetos (envío de métodos virtuales, ...). –

+0

mindmodel, aunque hay algunos escenarios para esto, si comienzas a necesitar herencia o [inserta cualquier otra restricción vs. métodos no estáticos] es un síntoma de que algo más podría estar apagado ... quizás la clase tenga demasiadas responsabilidades – eglasius

0

Tener en cuenta que un método estático shoudn't relé de datos de instancia ... usted debe tener una "MiMetodo" estática que se comporta diferentes en base a un parámetro o algo por el estilo.

Recuerde que el método estático definido en una clase es solo una forma de pedir su código ... pero es lo mismo si ese método se coloca en otra parte ... porque no se retransmite en el objeto donde está metido.

EDIT: Creo que su mejor elección es usar Product.MyMethod explícitamente ... Si lo cree ... no debería ser probable que su Widget cambie su clase base ... y también en ese caso es un cambio menor en el código.

+0

No es completamente cierto. los métodos estáticos pueden depender de miembros privados de un tipo (tanto estáticos como de instancia), como resultado, no son completamente móviles. –

+0

cierto. Usted conoce la diferencia entre las variables estáticas (una por clase) y las variables de instancia (una por instancia). ¿Por qué esta distinción no es útil? ¿Por qué es malo el diseño de OO? – MindModel

+0

Bueno, debería haber dicho que "No debería" no retransmitir en datos variables de instancia ... por supuesto que "PUEDE". :) – Romias

1

Los métodos estáticos no son polimórficos, por lo que lo que quieres hacer es imposible.

Tratar de encontrar una manera de tratar los métodos estáticos como polimórficos es posible pero peligroso, porque el lenguaje en sí mismo no lo admite.

Algunas sugerencias:

4

Se puede hacer, pero yo no lo recomiendo.

public class Parent1 
{ 
    public static void Foo() 
    { 
     Console.WriteLine("Parent1"); 
    } 
} 

public class Child : Parent1 
{ 
    public new static void Foo() 
    { 
     Type parent = typeof(Child).BaseType; 
     MethodInfo[] methods = parent.GetMethods(); 
     MethodInfo foo = methods.First(m => m.Name == "Foo"); 
     foo.Invoke(null, null); 
    } 
} 
+4

Bastante justo. En este caso, la solución es peor que el problema. Gracias. – MindModel

+0

Exactamente. Diez caracteres – marcumka

+2

en lugar de usar cadena, puede usar MethodBase.GetCurrentMethod(). Name –

0

Los métodos estáticos son métodos "de nivel de clase". Están destinados a ser métodos que se aplican a todas las instancias de una clase específica. Por lo tanto, la herencia de este método no tiene sentido ya que cambiaría el significado para aplicar a las instancias de la clase. Por ejemplo, si recorría una colección de Productos (algunos de Widget, otros no) y llamaba MyMethod a cada Producto, entonces el método que se llamaba estaría determinado por la instancia de la clase. Esto viola el propósito de los métodos estáticos.

Probablemente pueda hacer algo como lo que quiere de forma más limpia simplemente no utilizando métodos estáticos, porque en su ejemplo no parece que MyMethod se aplique a todas las instancias de Producto. Sin embargo, puede lograr el mismo efecto que está describiendo al usar una clase de interfaz como 'IMyMethod'. Este enfoque aún no usa un método estático. Supongo que no veo la necesidad de un método estático. ¿Por qué quieres usar un método estático para empezar?

4

Llamar a un método estático utilizando la reflexión es exactamente lo mismo que llamar a un método de instancia, excepto que pasa nulo para la instancia. Necesita FlattenHierarchy porque está definido en un ancestro.

var type = assy.GetType("MyNamespace.MyType"); 
MethodInfo mi = type.GetMethod("MyStaticMethod", 
    BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); 
mi.Invoke(null, null); 

Leer más y pensar me deja haciendo las mismas preguntas que otros que han respondido: ¿por qué usar métodos estáticos como este? ¿Estás tratando de hacer programación funcional, y si es así por qué no usar expresiones lambda en su lugar? Si desea comportamientos polimórficos con estado compartido, los métodos de instancia serían mejores.

-1

Es muy simple. Mucho más simple que usar aliasing, reflexiones, etc. Tal vez se ha hecho más fácil en nuevas incorporaciones de .NET, IDK, pero esto funciona perfectamente bien. Al igual que con los métodos de instancia, el acceso a los métodos base no requiere el uso de base, es opcional, generalmente es necesario cuando la clase heredada y la base tienen un método del mismo nombre. Incluso sin la palabra clave base, puede acceder a los métodos estáticos de una clase base como si estuvieran en la clase desde la que está llamando. Solo lo probé cuando llamé a un método estático de una clase derivada de método estático. Podría no funcionar si está llamando desde un método de instancia a un método estático.

public class BaseThings 
{ 
    protected static void AssertPermissions() 
    { 
     //something 
    } 
} 

public class Person:BaseThings 
{ 
    public static void ValidatePerson(Person person) 
    { 
     //just call the base static method as if it were in this class. 
     AssertPermissions();    
    } 
} 
+0

Aaron, OP tiene el mismo nombre de método para las clases base y derivadas. Junto con el hecho de que no quiere especificar 'Base.StaticMethod' explícitamente, estos dos son la clave del problema. – nawfal

2

En primer lugar, si usted está preocupado acerca de volver a la crianza de una clase, entonces usted está probablemente haciendo mal herencia. La herencia debe usarse para establecer relaciones "is-a", no simplemente para fomentar la reutilización del código. Si necesita volver a usar el código solo, considere usar delegación, en lugar de herencia. Supongo que podría introducir un tipo intermedio entre un subtipo y su padre, pero dejaría que esa posibilidad impulse mi diseño.

En segundo lugar, si necesita usar funcionalidades de la clase base pero ampliarlas Y el caso de uso requiere un método estático, entonces puede considerar usar alguna clase externa para mantener la funcionalidad. El caso clásico para esto en mi mente es el patrón de fábrica. Una forma de implementar el patrón Factory es a través de Factory Methods, un método estático en una clase que construye una instancia de esa clase. Por lo general, el constructor está protegido, por lo que el método de fábrica es la única forma de construir la clase desde el exterior.

Una forma de abordar la reutilización con Factory Methods en una jerarquía de herencia sería poner el código común en un método protegido y llamar a ese método desde Factory Method en lugar de llamar directamente a la clase base Factory Method desde un sub- tipos Método de fábrica. Una mejor implementación podría usar la misma técnica pero mover los métodos de fábrica a una clase de fábrica y usar la lógica del constructor (interna ahora, no privada), quizás junto con un método (s) de inicialización, para crear el objeto. Si el comportamiento que está heredando es externo a la clase (descifrado/validación/etc.), puede usar métodos compartidos (o composición) dentro de la fábrica para permitir la reutilización entre los métodos de fábrica.

Sin conocer el objetivo de su uso de métodos estáticos, es difícil darle una dirección exacta, pero espero que esto ayude.

2

Se puede hacer:

public class Parent1 
{ 
    protected static void Foo() 
    { 
     Console.WriteLine("Parent1"); 
    } 
} 

public class Child : Parent1 
{ 
    public static void Foo() 
    { 
     return Parent1.Foo(); 
    } 
} 

puede ser útil para las pruebas unitarias métodos estáticos protegidas (por ejemplo).

Cuestiones relacionadas