Últimamente he estado trabajando con proveedores , y me encontré con una situación interesante en la que quería tener una clase abstracta que tuviera un método estático abstracto. Leí algunas publicaciones sobre el tema, y tenía sentido, pero ¿hay alguna explicación clara y agradable?
c#
.net
language-design
lomaxx
fuente
fuente
Respuestas:
Los métodos estáticos no son instanciados como tales, solo están disponibles sin una referencia de objeto.
Una llamada a un método estático se realiza a través del nombre de la clase, no a través de una referencia de objeto, y el código del lenguaje intermedio (IL) para llamarlo llamará al método abstracto a través del nombre de la clase que lo definió, no necesariamente el nombre de la clase que usaste
Déjame mostrarte un ejemplo.
Con el siguiente código:
Si llamas a B.Test, así:
Entonces el código real dentro del método Main es el siguiente:
Como puede ver, la llamada se realiza a A.Test, porque fue la clase A la que lo definió, y no a B.Test, aunque puede escribir el código de esa manera.
Si tuviera tipos de clase , como en Delphi, donde puede hacer una variable que se refiera a un tipo y no a un objeto, tendría más uso para métodos estáticos virtuales y, por lo tanto, abstractos (y también constructores), pero no están disponibles y así, las llamadas estáticas no son virtuales en .NET.
Me doy cuenta de que los diseñadores de IL podrían permitir que el código se compile para llamar a B.Test y resolver la llamada en tiempo de ejecución, pero aún así no sería virtual, ya que aún tendría que escribir algún tipo de nombre de clase allí.
Los métodos virtuales, y por lo tanto los abstractos, solo son útiles cuando está utilizando una variable que, en tiempo de ejecución, puede contener muchos tipos diferentes de objetos, y por lo tanto desea llamar al método correcto para el objeto actual que tiene en la variable. Con los métodos estáticos, debe pasar por un nombre de clase de todos modos, por lo que el método exacto para llamar se conoce en tiempo de compilación porque no puede cambiar ni cambiará.
Por lo tanto, los métodos estáticos virtuales / abstractos no están disponibles en .NET.
fuente
Test()
es enA
lugar de ser abstracta y potencialmente definida enB
. \Car
tipo con unCreateFromDescription
método de fábrica estática virtual , entonces el código que aceptaba unCar
tipo genérico restringidoT
podría llamarT.CreateFromDescription
para producir un automóvil de tipoT
. Tal construcción podría ser soportada bastante bien dentro del CLR si cada tipo que definiera dicho método tuviera una instancia única estática de una clase genérica anidada que contuviera los métodos "estáticos" virtuales.Los métodos estáticos no pueden heredarse ni anularse, y es por eso que no pueden ser abstractos. Dado que los métodos estáticos se definen en el tipo, no en la instancia, de una clase, deben llamarse explícitamente en ese tipo. Entonces, cuando desee llamar a un método en una clase secundaria, debe usar su nombre para llamarlo. Esto hace que la herencia sea irrelevante.
Suponga que, por un momento, podría heredar métodos estáticos. Imagina este escenario:
Si llama a Base.GetNumber (), ¿qué método se llamaría? ¿Qué valor devuelto? Es bastante fácil ver que sin crear instancias de objetos, la herencia es bastante difícil. Los métodos abstractos sin herencia son solo métodos que no tienen cuerpo, por lo que no se pueden llamar.
fuente
int DoSomething<T>() where T:Base {return T.GetNumber();}
. Parecería útil siDoSomething<Base>()
pudiera devolver cinco, mientrasDoSomething<Child2>()
que devolvería dos. Dicha habilidad no solo sería útil para ejemplos de juguetes, sino también para algo asíclass Car {public static virtual Car Build(PurchaseOrder PO);}
, donde cada clase derivadaCar
tendría que definir un método que pudiera construir una instancia dada una orden de compra.Otro encuestado (McDowell) dijo que el polimorfismo solo funciona para instancias de objetos. Eso debería estar calificado; hay lenguajes que tratan las clases como instancias de un tipo "Clase" o "Metaclase". Estos lenguajes admiten el polimorfismo tanto para los métodos de instancia como de clase (estáticos).
C #, como Java y C ++ antes, no es tal lenguaje; la
static
palabra clave se usa explícitamente para indicar que el método está vinculado estáticamente en lugar de dinámico / virtual.fuente
Aquí hay una situación en la que definitivamente hay una necesidad de herencia para los campos y métodos estáticos:
fuente
legs
debería ser una propiedad abstracta estática.Para agregar a las explicaciones anteriores, las llamadas a métodos estáticos están vinculadas a un método específico en tiempo de compilación , que más bien descarta el comportamiento polimórfico.
fuente
De hecho, anulamos los métodos estáticos (en delphi), es un poco feo, pero funciona bien para nuestras necesidades.
Lo usamos para que las clases puedan tener una lista de sus objetos disponibles sin la instancia de clase, por ejemplo, tenemos un método que se ve así:
Es feo pero necesario, de esta manera podemos crear instancias de lo que se necesita, en lugar de tener todas las clases instanciadas solo para buscar los objetos disponibles.
Este fue un ejemplo simple, pero la aplicación en sí misma es una aplicación cliente-servidor que tiene todas las clases disponibles en un solo servidor y múltiples clientes diferentes que pueden no necesitar todo lo que tiene el servidor y nunca necesitarán una instancia de objeto.
Esto es mucho más fácil de mantener que tener una aplicación de servidor diferente para cada cliente.
Espero que el ejemplo sea claro.
fuente
Los métodos abstractos son implícitamente virtuales. Los métodos abstractos requieren una instancia, pero los métodos estáticos no tienen una instancia. Por lo tanto, puede tener un método estático en una clase abstracta, simplemente no puede ser un resumen estático (o un resumen estático).
fuente