Pregunta

Recientemente me encontré con un problema donde parece que necesito un "estático abstracto' método.Yo sé por qué es imposible, pero ¿cómo puedo evitar esta limitación?

Por ejemplo yo tengo una clase abstracta que tiene una cadena de descripción.Debido a que esta cadena es común para todos los casos, es marcado como static, pero quiero exigir que todas las clases derivadas de esta clase de proporcionar su propia Descripción de la propiedad por lo que he marcado como resumen:

abstract class AbstractBase
{
    ...
    public static abstract string Description{get;}
    ...
}

No va a compilar, por supuesto.Pensé en el uso de interfaces las interfaces, pero no puede contener método estático de las firmas.

Debo hacer es simplemente no estático, y siempre obtener una instancia para obtener esa clase de información específica?

Alguna idea?

¿Fue útil?

Solución

La combinación de estática y abstracta no tiene sentido, sí. La idea detrás de static es que uno no necesita presentar una instancia de la clase para usar el miembro en cuestión; sin embargo, con abstract, se espera que una instancia sea de una clase derivada que proporcione una implementación concreta.

Puedo ver por qué querrías este tipo de combinación, pero el hecho es que el único efecto sería negar el uso de la implementación de 'esto' o cualquier miembro no estático. Es decir, la clase padre dictaría una restricción en la implementación de la clase derivada, aunque no haya una diferencia subyacente entre llamar a un miembro abstracto o 'abstracto estático' (ya que ambos necesitarían una instancia concreta para determinar qué implementación usar)

Otros consejos

No puedes.

El lugar para hacer esto es con Atributos.

Ej.

[Name("FooClass")]
class Foo
{
}

Si no le importa aplazar las implementaciones para implementar de manera sensata la propiedad Descripción, simplemente puede hacer

public abstract string ClassDescription {get; } 
// ClassDescription is more intention-revealing than Description

Y la implementación de clases haría algo como esto:

static string classDescription="My Description for this class";
override string  ClassDescription { get { return classDescription; } }

Entonces, se requiere que sus clases sigan el contrato de tener una descripción, pero usted les deja que lo hagan con sensatez. No hay forma de especificar una implementación orientada a objetos (excepto a través de hacks crueles y frágiles).

Sin embargo, en mi opinión, esta Descripción son metadatos de clase, por lo que preferiría usar el mecanismo de atributo como otros han descrito. Si está particularmente preocupado por los múltiples usos de la reflexión, cree un objeto que refleje el atributo que le interesa y almacene un diccionario entre el Tipo y la Descripción. Eso minimizará el reflejo (aparte de la inspección de tipo de tiempo de ejecución, que no es tan malo). El diccionario se puede almacenar como miembro de cualquier clase que normalmente necesite esta información o, si los clientes de todo el dominio lo requieren, a través de un objeto singleton o de contexto.

Si es estático, solo hay una instancia de la variable, no veo cómo la herencia tendría sentido si pudiéramos hacer lo que quiere lograr con variables estáticas en clases derivadas. Personalmente, creo que irás demasiado lejos para tratar de evitar una instancia var.

¿Por qué no solo la forma clásica?

abstract class AbstractBase
{
    protected string _Description = "I am boring abstract default value";
}

class Foo : AbstractBase {

     public Foo() {
       _Description = "I am foo!";
     }
}

No es estático si debe llamarse en una instancia.

Si no lo está llamando en una instancia, entonces no hay ningún polimorfismo en juego (es decir, ChildA.Description no tiene ninguna relación con ChildB.Description en lo que respecta al idioma).

Una posible solución es definir un Singleton de la clase derivada en su clase base con la ayuda de medicamentos Genéricos.

import System;

public abstract class AbstractBase<T>
    where T : AbstractBase<T>, new()
{
    private static T _instance = new T();

    public abstract string Description { get; }
    public static string GetDescription()
    {
        return _instance.Description;
    }
}

public class DerivedClass : AbstractBase<DerivedClass>
{
    public override string Description => "This is the derived Class";
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(DerivedClass.GetDescription());
        Console.ReadKey();
    }
}

El truco es saber su AbstractBase<T> algunos detalles acerca de cómo DerivedClass se implementa:

  • Es newable con where T: new() así se puede crear una instancia Singleton
  • Se deriva de sí mismo con where T : AbstractBase<T> por lo que sabe que no va a ser una aplicación de Description

De esta manera _instance contiene la Description campo que puede ser llamado en el Método estático GetDescription().Esto obliga a sobrescribir Descriptionen su DerivedClass y le permite llamar a su valor con DerivedClass.GetDescription()

Puede hacer que " abstract " método base arroje un Exception, entonces un desarrollador es " advirtió " si intenta invocar este método en una clase secundaria sin anular.

La desventaja es que uno podría extender la clase y no usar este método. Luego consulte otras respuestas proporcionadas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top