En las respuestas a esta pregunta, el consenso general fue que los métodos estáticos no están destinados a ser anulados (y, por lo tanto, las funciones estáticas en C # no pueden ser virtuales o abstractas). Sin embargo, este no es solo el caso en C #; Java también prohíbe esto y a C ++ tampoco parece gustarle. Sin embargo, puedo pensar en muchos ejemplos de funciones estáticas que me gustaría anular en una clase secundaria (por ejemplo, métodos de fábrica). Si bien, en teoría, hay formas de evitarlos, ninguno de ellos es limpio o simple.
¿Por qué no deberían anularse las funciones estáticas?
object-oriented-design
abstract-class
static-methods
PixelArtDragon
fuente
fuente
self
puntero que apunta a la clase y no a una instancia de la clase.Respuestas:
Con los métodos estáticos, no hay ningún objeto para proporcionar un control adecuado del mecanismo de anulación.
El mecanismo de método virtual de clase / instancia normal permite un control finamente ajustado de las anulaciones de la siguiente manera: cada objeto real es una instancia de exactamente una clase. Esa clase determina el comportamiento de las anulaciones; siempre tiene la primera grieta en los métodos virtuales. Luego puede elegir llamar al método padre en el momento adecuado para su implementación. Cada método padre también tiene su turno para invocar su método padre. Esto da como resultado una buena cascada de invocaciones de padres, que cumple una de las nociones de reutilización de código por la que se conoce la orientación a objetos. (Aquí el código de las clases base / súper se está reutilizando de una manera relativamente compleja; otra noción ortogonal de reutilización de código en OOP es simplemente tener múltiples objetos de la misma clase).
Varias subclases pueden reutilizar las clases base, y cada una puede coexistir cómodamente. Cada clase que se usa para instanciar objetos dictando su propio comportamiento, coexistiendo pacíficamente y simultáneamente con los demás. El cliente tiene control sobre qué comportamientos quiere y cuándo elige qué clase usar para crear una instancia de un objeto y pasarlo a otros según lo desee.
(Este no es un mecanismo perfecto, ya que uno siempre puede identificar capacidades que no son compatibles, por supuesto, por eso los patrones como el método de fábrica y la inyección de dependencia se superponen en capas).
Entonces, si tuviéramos que hacer una capacidad de anulación para las estadísticas sin cambiar nada más, tendríamos dificultades para ordenar las anulaciones. Sería difícil definir un contexto limitado para la aplicabilidad de la anulación, por lo que obtendría la anulación globalmente en lugar de más localmente como con los objetos. No hay objeto de instancia para cambiar el comportamiento. Entonces, si alguien invocó el método estático que fue reemplazado por otra clase, ¿la anulación debería tener control o no? Si hay varias anulaciones de este tipo, ¿quién obtiene el control primero? ¿segundo? Con la anulación de objetos de instancia, todas estas preguntas tienen respuestas significativas y bien razonadas, pero con estática no.
Las anulaciones para la estática serían sustancialmente caóticas, y cosas como esta se han hecho antes.
Por ejemplo, Mac OS System 7 y anteriores usaban un mecanismo de parcheo de trampa para extender el sistema al obtener el control de las llamadas al sistema hechas por la aplicación antes que el sistema operativo. Podría pensar en la tabla de parches de llamadas del sistema como una matriz de punteros de función, muy parecida a una vtable para objetos de ejemplo, excepto que era una sola tabla global.
Esto causó un dolor incalculable para los programadores debido a la naturaleza desordenada de los parches de trampa. El que parche la trampa al final básicamente ganó, incluso si no quisieron. Cada parcheador de la captura capturaría el valor de la trampa anterior para una especie de capacidad de llamada principal, que era extremadamente frágil. Eliminar un parche de trampa, por ejemplo, cuando ya no necesita saber sobre una llamada al sistema se consideró una mala forma, ya que realmente no tenía la información necesaria para eliminar su parche (si lo hiciera, también quitaría el parche de cualquier otro parche que hubiera seguido tú).
Esto no quiere decir que sería imposible crear un mecanismo para anular las estadísticas, pero lo que probablemente preferiría hacer es convertir los campos estáticos y los métodos estáticos en campos de instancias y métodos de instancias de metaclases, de modo que el objeto normal entonces se aplicarían técnicas de orientación. Tenga en cuenta que también hay sistemas que hacen esto: CSE 341: clases y metaclases de Smalltalk ; Ver también: ¿Cuál es el equivalente de Smalltalk de la estática de Java?
Estoy tratando de decir que tendrías que hacer un diseño de características de lenguaje serio para que funcione incluso razonablemente bien. Por ejemplo, se hizo un enfoque ingenuo, cojeó, pero fue muy problemático y podría decirse (es decir, argumentaría) que tenía fallas arquitectónicas al proporcionar una abstracción incompleta y difícil de usar.
Cuando haya terminado de diseñar la función de anulaciones estáticas para que funcione bien, es posible que haya inventado alguna forma de metaclases, que es una extensión natural de OOP en / para métodos basados en clases. Entonces, no hay razón para no hacer esto, y algunos idiomas realmente lo hacen. Tal vez es solo un requisito adicional que varios idiomas eligen no hacer.
fuente
this.instanceMethod()
tiene una resolución dinámica, por lo que siself.staticMethod()
tiene la misma resolución, es decir, dinámica, ya no sería un método estático.La anulación depende del despacho virtual: utiliza el tipo de tiempo de ejecución del
this
parámetro para decidir a qué método llamar. Un método estático no tienethis
parámetros, por lo que no hay nada que enviar.Algunos lenguajes, especialmente Delphi y Python, tienen un alcance "intermedio" que permite esto: métodos de clase. Un método de clase no es un método de instancia ordinario, pero tampoco es estático; recibe un
self
parámetro (de forma divertida, ambos idiomas llamanthis
parámetroself
) que es una referencia al tipo de objeto en sí mismo, en lugar de una instancia de ese tipo. Con ese valor, ahora tiene un tipo disponible para hacer despacho virtual.Desafortunadamente, ni la JVM ni el CLR tienen nada comparable.
fuente
self
que tienen clases como objetos reales e instanciados con métodos reemplazables: Smalltalk, por supuesto, Ruby, Dart, Objective C, Self, Python? En comparación con los lenguajes que toman después de C ++, donde las clases no son objetos de primera clase, incluso si hay algún acceso de reflexión.virtual
y luego anularse en una clase descendiente, al igual que los métodos de instancia.Usted pregunta
Pregunto
Ciertos idiomas te obligan a iniciar el espectáculo en un método estático. Pero después de eso, realmente puede resolver una gran cantidad de problemas sin más métodos estáticos.
A algunas personas les gusta usar métodos estáticos cada vez que no hay dependencia del estado en un objeto. A algunas personas les gusta usar métodos estáticos para la construcción de otros objetos. A algunas personas les gusta evitar los métodos estáticos tanto como sea posible.
Ninguna de estas personas está equivocada.
Si necesita que se pueda anular, simplemente deje de etiquetarlo como estático. Nada se romperá porque tienes un objeto apátrida volando.
fuente
_start()
símbolo en Linux). En ese ejemplo, el ejecutable es el objeto (tiene su propia "tabla de despacho" y todo) y el punto de entrada es la operación despachada dinámicamente. Por lo tanto, el punto de entrada de un programa es inherentemente virtual cuando se ve desde el exterior y también se puede hacer que parezca virtual cuando se ve desde el interior.No es una cuestión de "debería".
"Anular" significa "despachar dinámicamente ". "Método estático" significa "despacho estático". Si algo es estático, no se puede anular. Si algo se puede anular, no es estático.
Su pregunta es bastante similar a preguntar: "¿Por qué los triciclos no deberían tener cuatro ruedas?" La definición de "triciclo" es que tiene tres ruedas. Si es un triciclo, no puede tener cuatro ruedas, si tiene cuatro ruedas, no puede ser un triciclo. Del mismo modo, la definición de "método estático" es que se envía estáticamente. Si es un método estático, no puede enviarse dinámicamente, si puede enviarse dinámicamente, no puede ser un método estático.
Por supuesto, es perfectamente posible tener métodos de clase que puedan ser anulados. O bien, podría tener un lenguaje como Ruby, donde las clases son objetos como cualquier otro objeto y, por lo tanto, pueden tener métodos de instancia, lo que elimina por completo la necesidad de métodos de clase. (Ruby solo tiene un tipo de métodos: métodos de instancia. No tiene métodos de clase, métodos estáticos, constructores, funciones o procedimientos).
fuente
En C #, siempre llama a miembros estáticos utilizando la clase, por ejemplo
BaseClass.StaticMethod()
, nobaseObject.StaticMethod()
. Finalmente, si tiene unaChildClass
herenciaBaseClass
ychildObject
una instancia deChildClass
, no podrá llamar a su método estático desdechildObject
. Siempre tendrá que usar explícitamente la clase real, porstatic virtual
lo que no tiene sentido.Lo que puede hacer es redefinir el mismo
static
método en su clase secundaria y usar lanew
palabra clave.Si fuera posible llamar
baseObject.StaticMethod()
, entonces su pregunta tendría sentido.fuente