Tengo varias clases que realmente no necesitan ningún estado. Desde el punto de vista organizativo, me gustaría ponerlos en jerarquía.
Pero parece que no puedo declarar herencia para clases estáticas.
Algo como eso:
public static class Base
{
}
public static class Inherited : Base
{
}
no trabajará.
¿Por qué los diseñadores del lenguaje han cerrado esa posibilidad?
c#
inheritance
static
Usuario
fuente
fuente
Respuestas:
Cita desde aquí :
Otras opiniones del canal 9
Y como una idea valiosa, littleguru tiene una "solución" parcial para este problema: el patrón Singleton .
fuente
object
, y se espera que todos lo sepan. Entonces, las clases estáticas siempre heredanobject
, ya sea que lo especifiques explícitamente o no.La razón principal por la que no puede heredar una clase estática es que son abstractos y sellados (esto también evita que se cree cualquier instancia de ellos).
Así que esto:
compila a esta IL:
fuente
Piénselo de esta manera: accede a miembros estáticos a través del nombre del tipo, así:
Si heredaras de esa clase, tendrías que acceder a ella a través del nuevo nombre de tipo:
Por lo tanto, el nuevo elemento no tiene relación con el original cuando se usa en el código. No habría forma de aprovechar una relación de herencia para cosas como el polimorfismo.
Quizás esté pensando que solo quiere extender algunos de los elementos de la clase original. En ese caso, no hay nada que le impida simplemente usar un miembro del original en un tipo completamente nuevo.
Quizás desee agregar métodos a un tipo estático existente. Puede hacerlo ya a través de métodos de extensión.
Quizás desee poder pasar una estática
Type
a una función en tiempo de ejecución y llamar a un método de ese tipo, sin saber exactamente qué hace el método. En ese caso, puede usar una interfaz.Entonces, al final, realmente no obtienes nada heredando clases estáticas.
fuente
SomeClass<T> where T:Foo
pueda acceder a miembros deFoo
, y siT
fuera una clase que anulara algunos miembros estáticos virtualesFoo
, la clase genérica usaría esas anulaciones. Probablemente incluso sería posible definir una convención a través de la cual los lenguajes pudieran hacerlo de una manera compatible con el CLR actual (por ejemplo, una clase con tales miembros debería definir una clase no estática protegida que contenga tales miembros de instancia, junto con un campo estático sosteniendo una instancia de ese tipo).Lo que desea lograr mediante el uso de la jerarquía de clases se puede lograr simplemente a través del espacio de nombres. Por lo tanto, los lenguajes que admiten espacios de nombres (como C #) no tendrán uso de implementar la jerarquía de clases de clases estáticas. Como no puede crear una instancia de ninguna de las clases, todo lo que necesita es una organización jerárquica de las definiciones de clase que puede obtener mediante el uso de espacios de nombres
fuente
Puede usar composición en su lugar ... esto le permitirá acceder a objetos de clase desde el tipo estático. Pero aún no puede implementar interfaces o clases abstractas
fuente
Aunque puede acceder a miembros estáticos "heredados" a través del nombre de las clases heredadas, los miembros estáticos no se heredan realmente. Esto es en parte por qué no pueden ser virtuales o abstractos y no pueden ser anulados. En su ejemplo, si declaró un Base.Method (), el compilador asignará una llamada a Inherited.Method () de nuevo a Base.Method () de todos modos. También podría llamar a Base.Method () explícitamente. Puede escribir una pequeña prueba y ver el resultado con Reflector.
Entonces ... si no puede heredar miembros estáticos, y si las clases estáticas solo pueden contener miembros estáticos, ¿de qué serviría heredar una clase estática?
fuente
Hmmm ... ¿sería muy diferente si solo tuvieras clases no estáticas llenas de métodos estáticos ...?
fuente
Una solución alternativa que puede hacer es no usar clases estáticas, sino ocultar el constructor para que los miembros estáticos de las clases sean lo único accesible fuera de la clase. El resultado es una clase "estática" heredable esencialmente:
Desafortunadamente debido a la limitación del lenguaje "por diseño" no podemos hacer:
fuente
Puede hacer algo que se verá como herencia estática.
Aquí está el truco:
Entonces puedes hacer esto:
La
Inherited
clase no es estática en sí misma, pero no permitimos crearla. En realidad, ha heredado el constructor estático que construyeBase
, y todas las propiedades y métodos deBase
disponibles como estáticos. Ahora, lo único que queda por hacer son envoltorios estáticos para cada método y propiedad que necesita exponer a su contexto estático.Hay inconvenientes como la necesidad de crear manualmente los métodos de envoltura estática y las
new
palabras clave. Pero este enfoque ayuda a soportar algo que es realmente similar a la herencia estática.PD: Usamos esto para crear consultas compiladas, y esto en realidad se puede reemplazar con ConcurrentDictionary, pero un campo de solo lectura estático con su seguridad de subprocesos fue lo suficientemente bueno.
fuente
Mi respuesta: mala elección de diseño. ;-)
Este es un debate interesante centrado en el impacto de la sintaxis. El núcleo del argumento, en mi opinión, es que una decisión de diseño condujo a clases estáticas selladas. ¿Un enfoque en la transparencia de los nombres de la clase estática que aparecen en el nivel superior en lugar de esconderse ('confundir') detrás de los nombres secundarios? Uno puede imaginar una implementación de lenguaje que podría acceder a la base o al niño directamente, confuso.
Un pseudo ejemplo, suponiendo que la herencia estática se definió de alguna manera.
daría lugar a:
que podría (afectaría) el mismo almacenamiento que
¡Muy confuso!
¡Pero espera! ¿Cómo trataría el compilador con MyStaticBase y MyStaticChild con la misma firma definida en ambos? Si el niño anula que mi ejemplo anterior NO cambiaría el mismo almacenamiento, ¿tal vez? Esto lleva a una mayor confusión.
Creo que existe una fuerte justificación del espacio informativo para la herencia estática limitada. Más sobre los límites en breve. Este pseudocódigo muestra el valor:
Entonces obtienes:
El uso se parece a:
La persona que crea el niño estático no necesita pensar en el proceso de serialización siempre y cuando comprenda las limitaciones que se pueden colocar en el motor de serialización de la plataforma o el entorno.
Las estadísticas (singletons y otras formas de 'globales') a menudo surgen en torno al almacenamiento de configuración. La herencia estática permitiría que este tipo de asignación de responsabilidad se representara limpiamente en la sintaxis para que coincida con una jerarquía de configuraciones. Sin embargo, como mostré, existe un gran potencial para una ambigüedad masiva si se implementan conceptos básicos de herencia estática.
Creo que la opción de diseño correcta sería permitir la herencia estática con limitaciones específicas:
Aún puede cambiar la misma tienda a través de una referencia genérica
MyStaticBase<ChildPayload>.SomeBaseField
. Pero se desanimaría ya que el tipo genérico tendría que especificarse. Si bien la referencia secundaria sería más limpia:MyStaticChild.SomeBaseField
.No soy un escritor compilador, así que no estoy seguro de si me falta algo sobre las dificultades de implementar estas limitaciones en un compilador. Dicho esto, creo firmemente que existe una necesidad de espacio informativo para una herencia estática limitada y la respuesta básica es que no se puede debido a una elección de diseño pobre (o demasiado simple).
fuente
Las clases estáticas y los miembros de la clase se utilizan para crear datos y funciones a las que se puede acceder sin crear una instancia de la clase. Los miembros de clase estática se pueden usar para separar datos y comportamientos que son independientes de cualquier identidad de objeto: los datos y las funciones no cambian independientemente de lo que le ocurra al objeto. Las clases estáticas se pueden usar cuando no hay datos o comportamiento en la clase que dependa de la identidad del objeto.
Una clase puede declararse estática, lo que indica que contiene solo miembros estáticos. No es posible utilizar la nueva palabra clave para crear instancias de una clase estática. Las clases estáticas se cargan automáticamente mediante .NET Framework Common Language Runtime (CLR) cuando se carga el programa o el espacio de nombres que contiene la clase.
Use una clase estática para contener métodos que no están asociados con un objeto en particular. Por ejemplo, es un requisito común crear un conjunto de métodos que no actúen sobre los datos de la instancia y que no estén asociados a un objeto específico en su código. Podría usar una clase estática para contener esos métodos.
Las siguientes son las características principales de una clase estática:
Solo contienen miembros estáticos.
No pueden ser instanciados.
Están sellados
No pueden contener constructores de instancias (Guía de programación de C #).
Por lo tanto, crear una clase estática es básicamente lo mismo que crear una clase que contenga solo miembros estáticos y un constructor privado. Un constructor privado evita que la clase sea instanciada.
La ventaja de usar una clase estática es que el compilador puede verificar para asegurarse de que no se agreguen accidentalmente miembros de la instancia. El compilador garantizará que no se puedan crear instancias de esta clase.
Las clases estáticas están selladas y, por lo tanto, no se pueden heredar. No pueden heredar de ninguna clase excepto Object. Las clases estáticas no pueden contener un constructor de instancias; sin embargo, pueden tener un constructor estático. Para obtener más información, consulte Constructores estáticos (Guía de programación de C #).
fuente
Cuando creamos una clase estática que contiene solo los miembros estáticos y un constructor privado. La única razón es que el constructor estático evita que la clase sea instanciada para que no podamos heredar una clase estática. La única forma de acceder al miembro del clase estática utilizando el nombre de la clase en sí. Intentar heredar una clase estática no es una buena idea.
fuente