¿Por qué no es posible anular los métodos estáticos?
Si es posible, utilice un ejemplo.
java
static
overriding
static-methods
Sgokhales
fuente
fuente
Parent p = new Child()
y luegop.childOverriddenStaticMethod()
el compilador lo resolveráParent.childOverriddenStaticMethod()
mirando el tipo de referencia.Respuestas:
La anulación depende de tener una instancia de una clase. El punto del polimorfismo es que puede subclasificar una clase y los objetos que implementan esas subclases tendrán comportamientos diferentes para los mismos métodos definidos en la superclase (y anulados en las subclases). Un método estático no está asociado con ninguna instancia de una clase, por lo que el concepto no es aplicable.
Hubo dos consideraciones que impulsaron el diseño de Java que impactaron esto. Una de ellas era la preocupación por el rendimiento: hubo muchas críticas a Smalltalk por ser demasiado lento (la recolección de basura y las llamadas polimórficas son parte de eso) y los creadores de Java estaban decididos a evitar eso. Otra fue la decisión de que el público objetivo de Java fueran los desarrolladores de C ++. Hacer que los métodos estáticos funcionen de la manera en que lo hicieron tuvo el beneficio de la familiaridad para los programadores de C ++ y también fue muy rápido, porque no hay necesidad de esperar hasta el tiempo de ejecución para descubrir qué método llamar.
fuente
objects
) permite la sobrecarga de métodos.obj.staticMethod()
), que está permitido y utiliza los tipos de tiempo de compilación. Cuando la llamada estática está en un método no estático de una clase, el objeto "actual" podría ser un tipo derivado de la clase, pero los métodos estáticos definidos en los tipos derivados no se consideran (están en el tipo de tiempo de ejecución jerarquía).Personalmente, creo que esto es un defecto en el diseño de Java. Sí, sí, entiendo que los métodos no estáticos se adjuntan a una instancia mientras que los métodos estáticos se adjuntan a una clase, etc. Aún así, considere el siguiente código:
Este código no funcionará como es de esperar. A saber, los empleados especiales obtienen una bonificación del 2% al igual que los empleados regulares. Pero si elimina los "estáticos", los empleados especiales recibirán un bono del 3%.
(Es cierto que este ejemplo es un estilo de codificación deficiente en el sentido de que en la vida real es probable que desee que el multiplicador de bonificación esté en una base de datos en algún lugar en lugar de estar codificado. Pero eso es solo porque no quería empantanar el ejemplo con mucho de código irrelevante para el punto.)
Me parece bastante plausible que desee hacer que getBonusMultiplier sea estático. Quizás desee poder mostrar el multiplicador de bonificación para todas las categorías de empleados, sin necesidad de tener una instancia de un empleado en cada categoría. ¿Cuál sería el punto de buscar ejemplos de este tipo? ¿Qué sucede si estamos creando una nueva categoría de empleados y todavía no tenemos empleados asignados? Esto es lógicamente una función estática.
Pero no funciona.
Y sí, sí, se me ocurren muchas formas de reescribir el código anterior para que funcione. Mi punto no es que crea un problema sin solución, sino que crea una trampa para el programador incauto, porque el lenguaje no se comporta como creo que una persona razonable esperaría.
Quizás si tratara de escribir un compilador para un lenguaje OOP, vería rápidamente por qué implementarlo para que las funciones estáticas puedan ser reemplazadas sería difícil o imposible.
O tal vez hay una buena razón por la cual Java se comporta de esta manera. ¿Alguien puede señalar una ventaja para este comportamiento, alguna categoría de problema que se facilita con esto? Quiero decir, no solo me señales la especificación del lenguaje Java y digas "mira, esto está documentado cómo se comporta". Yo sé eso. ¿Pero hay una buena razón por la que DEBE comportarse de esta manera? (Además del obvio "hacer que funcione bien fue demasiado difícil" ...)
Actualizar
@VicKirk: Si quiere decir que este es un "mal diseño" porque no se ajusta a cómo Java maneja las estadísticas, mi respuesta es: "Bueno, claro, por supuesto". Como dije en mi publicación original, no funciona. Pero si quiere decir que es un mal diseño en el sentido de que habría algo fundamentalmente incorrecto con un lenguaje en el que esto funcionara, es decir, donde las estadísticas podrían anularse al igual que las funciones virtuales, eso de alguna manera introduciría una ambigüedad o sería imposible implementar de manera eficiente o algo así, respondo: "¿Por qué? ¿Qué tiene de malo el concepto?
Creo que el ejemplo que doy es algo muy natural que quiero hacer. Tengo una clase que tiene una función que no depende de ningún dato de instancia, y que razonablemente podría querer llamar independientemente de una instancia, además de querer llamar desde un método de instancia. ¿Por qué esto no debería funcionar? Me he encontrado con esta situación varias veces a lo largo de los años. En la práctica, lo evito haciendo que la función sea virtual, y luego creando un método estático cuyo único propósito en la vida es ser un método estático que pase la llamada al método virtual con una instancia ficticia. Esa parece ser una forma indirecta de llegar allí.
fuente
someStatic()
y B extiende A, luego seB.someMethod()
une al método en A. Si posteriormente agregosomeStatic()
a B, el código de llamada aún se invocaA.someStatic()
hasta que vuelva a compilar el código de llamada. También me sorprendió quebInstance.someStatic()
use el tipo declarado de bInstance, no el tipo de tiempo de ejecución porque se une al compilar y no al enlace, por lo queA bInstance; ... bInstance.someStatic()
invoca A.someStatic () si existe B.someStatic ().La respuesta corta es: es completamente posible, pero Java no lo hace.
Aquí hay un código que ilustra el estado actual de las cosas en Java:
Archivo
Base.java
:Archivo
Child.java
:Si ejecuta esto (lo hice en una Mac, desde Eclipse, usando Java 1.6) obtendrá:
Aquí, los únicos casos que podrían ser una sorpresa (y sobre los que trata la pregunta) parecen ser el primer caso:
"El tipo de tiempo de ejecución no se utiliza para determinar qué métodos estáticos se llaman, incluso cuando se llama con una instancia de objeto (
obj.staticMethod()
)".y el último caso:
"Cuando se llama a un método estático desde un método de objeto de una clase, el método estático elegido es el accesible desde la propia clase y no desde la clase que define el tipo de tiempo de ejecución del objeto".
Llamar con una instancia de objeto
La llamada estática se resuelve en tiempo de compilación, mientras que una llamada de método no estático se resuelve en tiempo de ejecución. Tenga en cuenta que aunque los métodos estáticos se heredan (del padre), no se anulan (por el niño). Esto podría ser una sorpresa si esperabas lo contrario.
Llamar desde un método de objeto
Las llamadas a métodos de objeto se resuelven usando el tipo de tiempo de ejecución, pero las llamadas a métodos estáticos (de clase ) se resuelven usando el tipo de tiempo de compilación (declarado).
Cambiando las reglas
Para cambiar estas reglas, para que la última llamada en el ejemplo llamado
Child.printValue()
, las llamadas estáticas tengan que proporcionarse con un tipo en tiempo de ejecución, en lugar de que el compilador resuelva la llamada en tiempo de compilación con la clase declarada del objeto (o contexto). Las llamadas estáticas podrían usar la jerarquía de tipos (dinámicos) para resolver la llamada, tal como lo hacen hoy las llamadas a métodos de objetos.Esto sería fácilmente factible (si cambiamos Java: -O), y no es en absoluto irrazonable, sin embargo, tiene algunas consideraciones interesantes.
La consideración principal es que debemos decidir qué llamadas a métodos estáticos deberían hacer esto.
Por el momento, Java tiene esta "peculiaridad" en el lenguaje por el cual las
obj.staticMethod()
llamadas se reemplazan porObjectClass.staticMethod()
llamadas (normalmente con una advertencia). [ Nota:ObjectClass
es el tipo de tiempo de compilación deobj
.] Estos serían buenos candidatos para anular de esta manera, tomando el tipo de tiempo de ejecución deobj
.Si lo hiciéramos, los cuerpos de los métodos serían más difíciles de leer: las llamadas estáticas en una clase primaria podrían potencialmente ser " reenrutadas " dinámicamente . Para evitar esto, tendríamos que llamar al método estático con un nombre de clase, y esto hace que las llamadas se resuelvan más obviamente con la jerarquía de tipo de tiempo de compilación (como ahora).
Las otras formas de invocar un método estático son más complicadas:
this.staticMethod()
deberían significar lo mismo queobj.staticMethod()
tomar el tipo de tiempo de ejecución dethis
. Sin embargo, esto podría causar algunos dolores de cabeza con los programas existentes, que llaman a métodos estáticos (aparentemente locales) sin decoración (que posiblemente sea equivalente athis.method()
).Entonces, ¿qué pasa con las llamadas sin adornos
staticMethod()
? Sugiero que hagan lo mismo que hoy y usen el contexto de clase local para decidir qué hacer. De lo contrario, se produciría una gran confusión. Por supuesto, significa que esomethod()
significaríathis.method()
simethod
fuera un método no estático yThisClass.method()
simethod
fuera un método estático. Esta es otra fuente de confusión.Otras Consideraciones
Si cambiamos este comportamiento (e hicimos llamadas estáticas potencialmente dinámicamente no locales), probablemente querríamos revisar el significado de
final
,private
yprotected
como calificadores, en losstatic
métodos de una clase. Tendríamos entonces todos tenemos que acostumbrarse al hecho de queprivate static
ypublic final
métodos no son anulados, y por tanto pueden ser resueltos de manera segura en tiempo de compilación, y es "seguro" para que lea como referencias locales.fuente
En realidad estábamos equivocados.
A pesar de que Java no le permite anular los métodos estáticos de manera predeterminada, si mira detenidamente la documentación de las clases Class y Method en Java, aún puede encontrar una manera de emular los métodos estáticos reemplazando la siguiente solución:
Resultado resultante:
lo que estábamos tratando de lograr :)
Incluso si declaramos la tercera variable Carl como RegularEmployee y le asignamos una instancia de SpecialEmployee, todavía tendremos que llamar al método RegularEmployee en el primer caso y llamar al método SpecialEmployee en el segundo caso
solo mira la consola de salida:
;)
fuente
La JVM trata los métodos estáticos como globales, no están vinculados a una instancia de objeto en absoluto.
Conceptualmente podría ser posible si pudieras llamar a métodos estáticos desde objetos de clase (como en lenguajes como Smalltalk) pero no es el caso en Java.
EDITAR
Puedes sobrecargar el método estático, está bien. Pero no puede anular un método estático, porque la clase no es un objeto de primera clase. Puede usar la reflexión para obtener la clase de un objeto en tiempo de ejecución, pero el objeto que obtiene no es paralelo a la jerarquía de clases.
Puedes reflexionar sobre las clases, pero se detiene allí. No invocas un método estático usando
clazz1.staticMethod()
, sino usandoMyClass.staticMethod()
. Un método estático no está vinculado a un objeto y, por lo tanto, no existe una nociónthis
nisuper
un método estático. Un método estático es una función global; Como consecuencia, tampoco existe una noción de polimorfismo y, por lo tanto, la anulación del método no tiene sentido.Pero esto podría ser posible si
MyClass
fuera un objeto en tiempo de ejecución en el que invoque un método, como en Smalltalk (o tal vez JRuby como sugiere un comentario, pero no sé nada de JRuby).Oh sí ... una cosa más. Puede invocar un método estático a través de un objeto,
obj1.staticMethod()
pero ese azúcar realmente sintácticoMyClass.staticMethod()
debe evitarse. Por lo general, genera una advertencia en el IDE moderno. No sé por qué alguna vez permitieron este atajo.fuente
clazz2 instanceof clazz1
correctamente, puede usarloclass2.isAssignableFrom(clazz1)
, lo que creo que sería cierto en su ejemplo.La anulación de métodos es posible mediante el despacho dinámico , lo que significa que el tipo declarado de un objeto no determina su comportamiento, sino su tipo de tiempo de ejecución:
Aunque ambos
lassie
ykermit
se declaran como objetos de tipoAnimal
, su comportamiento (método.speak()
) varía porque el despacho dinámico solo vinculará la llamada.speak()
al método a una implementación en tiempo de ejecución, no en tiempo de compilación.Ahora, aquí es donde la
static
palabra clave comienza a tener sentido: la palabra "estática" es un antónimo de "dinámico". Entonces, la razón por la que no puede anular los métodos estáticos es porque no hay despacho dinámico en miembros estáticos, porque estático literalmente significa "no dinámico". Si se despacharan dinámicamente (y, por lo tanto, podrían anularse), lastatic
palabra clave ya no tendría sentido.fuente
Si. Prácticamente Java permite anular el método estático, y no teóricamente si anula un método estático en Java, se compilará y ejecutará sin problemas, pero perderá el polimorfismo, que es la propiedad básica de Java. Leerá en todas partes que no es posible intentar compilar y ejecutar. Obtendrás tu respuesta. por ejemplo, si tiene Class Animal y un método estático eat () y anula ese método estático en su subclase, vamos a llamarlo Dog. Entonces, cuando sea que asigne un objeto Perro a una Referencia de animal y llame a eat () de acuerdo con Java, se debería haber llamado eat () pero en estática Overriding Animals 'eat () se llamará.
Según el principio de polimorfismo de Java, la salida debería ser
Dog Eating
.Pero el resultado fue diferente porque para admitir el polimorfismo, Java utiliza enlace tardío, lo que significa que los métodos se invocan solo en el tiempo de ejecución, pero no en el caso de los métodos estáticos. En los métodos estáticos, el compilador llama a los métodos en el momento de la compilación en lugar del tiempo de ejecución, por lo que obtenemos métodos de acuerdo con la referencia y no de acuerdo con el objeto, una referencia que contiene, por eso. 't.
fuente
la anulación está reservada para miembros de instancia para admitir el comportamiento polimórfico. los miembros de la clase estática no pertenecen a una instancia particular. en cambio, los miembros estáticos pertenecen a la clase y, como resultado, no se admite la anulación porque las subclases solo heredan miembros de instancia públicos y protegidos y no miembros estáticos. Es posible que desee definir una fábrica de interfaz e investigación y / o patrones de diseño de estrategia para evaluar un enfoque alternativo.
fuente
En Java (y en muchos lenguajes OOP, pero no puedo hablar por todos; y algunos no tienen estática), todos los métodos tienen una firma fija: los parámetros y los tipos. En un método virtual, el primer parámetro está implícito: una referencia al objeto en sí mismo y cuando se llama desde dentro del objeto, el compilador agrega automáticamente
this
.No hay diferencia para los métodos estáticos: todavía tienen una firma fija. Sin embargo, al declarar el método estático, ha declarado explícitamente que el compilador no debe incluir el parámetro de objeto implícito al comienzo de esa firma. Por lo tanto, cualquier otro código que llame a esto no debe intentar poner una referencia a un objeto en la pila . Si lo hiciera, la ejecución del método no funcionaría ya que los parámetros estarían en el lugar incorrecto, desplazado por uno, en la pila.
Debido a esta diferencia entre los dos; Los métodos virtuales siempre tienen una referencia al objeto de contexto (es decir
this
), por lo que es posible hacer referencia a cualquier cosa dentro del montón que pertenezca a esa instancia del objeto. Pero con los métodos estáticos, dado que no se pasa ninguna referencia, ese método no puede acceder a ninguna variable de objeto y métodos ya que el contexto no se conoce.Si desea que Java cambie la definición para que se pase un contexto de objeto para cada método, estático o virtual, entonces, en esencia, solo tendría métodos virtuales.
Como alguien preguntó en un comentario a la operación, ¿cuál es su razón y propósito para querer esta función?
No conozco mucho a Ruby, ya que esto fue mencionado por el OP, investigué un poco. Veo que en Ruby las clases son realmente un tipo especial de objeto y uno puede crear (incluso dinámicamente) nuevos métodos. Las clases son objetos de clase completa en Ruby, no están en Java. Esto es algo que tendrá que aceptar cuando trabaje con Java (o C #). Estos no son lenguajes dinámicos, aunque C # está agregando algunas formas de dinámicas. En realidad, Ruby no tiene métodos "estáticos" por lo que pude encontrar, en ese caso estos son métodos en el objeto de clase singleton. Luego puede anular este singleton con una nueva clase y los métodos del objeto de clase anterior llamarán a los definidos en la nueva clase (¿correcto?). Entonces, si llamó a un método en el contexto de la clase original, todavía solo ejecutaría las estadísticas originales, pero llamar a un método en la clase derivada, llamaría a los métodos desde el padre o la subclase. Interesante y puedo ver algo de valor en eso. Se necesita un patrón de pensamiento diferente.
Como está trabajando en Java, tendrá que adaptarse a esa forma de hacer las cosas. ¿Por qué hicieron esto? Bueno, probablemente para mejorar el rendimiento en el momento en función de la tecnología y la comprensión que estaba disponible. Los lenguajes informáticos están en constante evolución. Regrese lo suficientemente lejos y no hay tal cosa como OOP. En el futuro, habrá otras ideas nuevas.
EDITAR : Otro comentario. Ahora que veo las diferencias y, como desarrollador de Java / C #, puedo entender por qué las respuestas que obtienes de los desarrolladores de Java pueden ser confusas si vienes de un lenguaje como Ruby. Los
static
métodos Java no son lo mismo que losclass
métodos Ruby . Los desarrolladores de Java tendrán dificultades para entender esto, al igual que aquellos que trabajan principalmente con un lenguaje como Ruby / Smalltalk. Puedo ver cómo esto también sería muy confuso por el hecho de que Java también usa el "método de clase" como otra forma de hablar sobre métodos estáticos, pero este mismo término es usado de manera diferente por Ruby. Java no tiene métodos de clase de estilo Ruby (lo siento); Ruby no tiene métodos estáticos de estilo Java, que en realidad son funciones de estilo de procedimiento antiguas, como se encuentra en C.Por cierto, ¡gracias por la pregunta! Hoy aprendí algo nuevo para mí sobre los métodos de clase (estilo Ruby).
fuente
Bueno ... la respuesta es NO si piensas desde la perspectiva de cómo debería comportarse un método anulado en Java. Pero no obtiene ningún error del compilador si intenta anular un método estático. Eso significa que, si intentas anular, Java no te impide hacerlo; pero ciertamente no obtienes el mismo efecto que obtienes para los métodos no estáticos. Reemplazar en Java simplemente significa que se llamará a un método en particular basado en el tipo de tiempo de ejecución del objeto y no en el tipo de tiempo de compilación del mismo (que es el caso con los métodos estáticos anulados). De acuerdo ... ¿adivinan por qué se comportan de manera extraña? Debido a que son métodos de clase y, por lo tanto, el acceso a ellos siempre se resuelve durante el tiempo de compilación solo usando la información del tipo de tiempo de compilación.
Ejemplo : intentemos ver qué sucede si intentamos anular un método estático: -
Salida : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod
Observe la segunda línea de la salida. Si se hubiera anulado el staticMethod, esta línea debería haber sido idéntica a la tercera línea ya que estamos invocando el 'staticMethod ()' en un objeto de Tipo de tiempo de ejecución como 'Subclase' y no como 'Superclase'. Esto confirma que los métodos estáticos siempre se resuelven utilizando únicamente su información de tipo de tiempo de compilación.
fuente
En general, no tiene sentido permitir 'anular' los métodos estáticos, ya que no habría una buena manera de determinar a cuál llamar en tiempo de ejecución. Tomando el ejemplo de Empleado, si llamamos a RegularEmployee.getBonusMultiplier (), ¿qué método se supone que debe ejecutarse?
En el caso de Java, uno podría imaginar una definición de lenguaje donde es posible 'anular' los métodos estáticos siempre que se invoquen a través de una instancia de objeto. Sin embargo, todo lo que haría sería volver a implementar métodos de clase regulares, agregando redundancia al lenguaje sin agregar realmente ningún beneficio.
fuente
Al anular podemos crear una naturaleza polimórfica dependiendo del tipo de objeto. El método estático no tiene relación con el objeto. Entonces, Java no puede soportar la anulación del método estático.
fuente
Me gusta y doblo el comentario de Jay ( https://stackoverflow.com/a/2223803/1517187 ).
Estoy de acuerdo en que este es el mal diseño de Java.
Muchos otros idiomas admiten métodos estáticos de anulación, como vemos en comentarios anteriores. Siento que Jay también llegó a Java desde Delphi como yo.
Delphi (Object Pascal) fue el primer lenguaje que implementó OOP.
Es obvio que muchas personas tenían experiencia con ese idioma, ya que en el pasado era el único idioma para escribir productos GUI comerciales. Y, sí, podríamos en Delphi anular los métodos estáticos. En realidad, los métodos estáticos en Delphi se llaman "métodos de clase", mientras que Delphi tenía el concepto diferente de "métodos estáticos Delphi", que eran métodos con enlace temprano. Para anular los métodos que tenía que usar el enlace tardío, declare la directiva "virtual". Así que fue muy conveniente e intuitivo y esperaría esto en Java.
fuente
¿De qué servirá para anular los métodos estáticos? No puede llamar a métodos estáticos a través de una instancia.
EDITAR: Parece que a través de una desafortunada supervisión en el diseño del lenguaje, puede llamar a métodos estáticos a través de una instancia. Generalmente nadie hace eso. Culpa mía.
fuente
variable.staticMethod()
, en lugar deClass.staticMethod()
, dóndevariable
es una variable con tipo declaradoClass
. Estoy de acuerdo en que es un mal diseño del lenguaje.Reemplazar en Java simplemente significa que el método particular se llamaría en función del tipo de tiempo de ejecución del objeto y no del tipo de tiempo de compilación del mismo (que es el caso con los métodos estáticos anulados). Como los métodos estáticos son métodos de clase, no son métodos de instancia, por lo que no tienen nada que ver con el hecho de qué referencia apunta a qué objeto o instancia, porque debido a la naturaleza del método estático pertenece a una clase específica. Puede volver a declararlo en la subclase, pero esa subclase no sabrá nada sobre los métodos estáticos de la clase principal porque, como dije, es específica solo de la clase en la que se ha declarado. Acceder a ellos utilizando referencias de objetos es solo una libertad adicional dada por los diseñadores de Java y ciertamente no debemos pensar en detener esa práctica solo cuando la restringen más detalles y ejemplos. http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html
fuente
Al anular, se logra un polimorfismo dinámico. Cuando dice que anula los métodos estáticos, las palabras que está tratando de usar son contradictorias.
La estática dice: tiempo de compilación, la anulación se usa para el polimorfismo dinámico. Ambos son de naturaleza opuesta y, por lo tanto, no se pueden usar juntos.
El comportamiento polimórfico dinámico se produce cuando un programador usa un objeto y accede a un método de instancia. JRE asignará diferentes métodos de instancia de diferentes clases según el tipo de objeto que esté utilizando.
Cuando dice que anula los métodos estáticos, a los métodos estáticos accederemos utilizando el nombre de la clase, que se vinculará en tiempo de compilación, por lo que no existe el concepto de vincular métodos en tiempo de ejecución con métodos estáticos. Por lo tanto, el término "sobrescribir" métodos estáticos en sí mismo no tiene ningún significado.
Nota: incluso si accede a un método de clase con un objeto, aún el compilador de Java es lo suficientemente inteligente como para descubrirlo y realizará enlaces estáticos.
fuente
Box.createBox
tiene más sentido que esoBoxFactory.createBox
, y es un patrón inevitable cuando se necesita verificar la construcción de errores sin lanzar excepciones (los constructores no pueden fallar, solo pueden matar el proceso / lanzamiento excepción), mientras que un método estático puede devolver nulo en caso de error, o incluso aceptar devoluciones de llamada de éxito / error para escribir algo como hastebin.com/codajahati.java .La respuesta a esta pregunta es simple, el método o la variable marcada como estática pertenece solo a la clase, de modo que el método estático no se puede heredar en la subclase porque pertenecen solo a la superclase.
fuente
Solución fácil: use instancia singleton. Permitirá anulaciones y herencia.
En mi sistema, tengo la clase SingletonsRegistry, que devuelve la instancia para la clase aprobada. Si no se encuentra la instancia, se crea.
Clase de idioma haxe:
fuente
Singleton.get()
. El registro es simplemente una sobrecarga, y excluye GC en las clases.Un método estático, variable, bloque o clase anidada pertenece a toda la clase en lugar de a un objeto.
Un método en Java se utiliza para exponer el comportamiento de un objeto / clase. Aquí, como el método es estático (es decir, el método estático se usa para representar el comportamiento de una clase solamente). Cambiar / anular el comportamiento de toda la clase violará el fenómeno de uno de los pilares fundamentales de la programación orientada a objetos, es decir, alta cohesión . (recuerde que un constructor es un tipo especial de método en Java).
Alta cohesión : una clase debe tener un solo rol. Por ejemplo: una clase de automóvil debe producir solo objetos de automóvil y no bicicletas, camiones, aviones, etc. Pero la clase de automóvil puede tener algunas características (comportamiento) que solo le pertenecen.
Por lo tanto, al diseñar el lenguaje de programación java. Los diseñadores de lenguaje pensaron permitir a los desarrolladores mantener algunos comportamientos de una clase para sí mismos solo al hacer que un método sea de naturaleza estática.
El siguiente código de pieza intenta anular el método estático, pero no encontrará ningún error de compilación.
Esto se debe a que aquí no estamos anulando un método, sino que simplemente lo estamos volviendo a declarar . Java permite la nueva declaración de un método (estático / no estático).
Eliminar la palabra clave estática del método getVehileNumber () de la clase Car dará como resultado un error de compilación, ya que estamos tratando de cambiar la funcionalidad del método estático que pertenece solo a la clase Vehicle.
Además, si getVehileNumber () se declara como final , el código no se compilará, ya que la palabra clave final restringe al programador de volver a declarar el método.
En general, esto depende de los diseñadores de software sobre dónde usar los métodos estáticos. Personalmente prefiero usar métodos estáticos para realizar algunas acciones sin crear ninguna instancia de una clase. En segundo lugar, para ocultar el comportamiento de una clase del mundo exterior.
fuente
Aquí hay una explicación simple. Un método estático está asociado con una clase, mientras que un método de instancia está asociado con un objeto en particular. Las anulaciones permiten llamar a la implementación diferente de los métodos anulados asociados con el objeto en particular. Por lo tanto, es contra-intuitivo anular el método estático que ni siquiera está asociado con los objetos, sino con la clase misma en primer lugar. Por lo tanto, los métodos estáticos no se pueden anular según el objeto que lo llama, siempre se asociará con la clase donde se creó.
fuente
public abstract IBox createBox();
interfaz interna de IBox? Box puede implementar IBox para anular createBox y hacer que la creación del objeto dé como resultado un IBox válido; de lo contrario, devolverá un valor nulo. Los constructores no pueden devolver "nulo" y, por lo tanto, se ve obligado a (1) usar excepciones EN TODAS PARTES (lo que hacemos ahora), o (2) crear clases de fábrica que hagan lo que dije antes, pero de una manera que no tiene sentido para principiantes ni expertos de Java (que también hacemos ahora). Los métodos estáticos no implementados resuelven esto.Ahora, viendo las respuestas anteriores, todos saben que no podemos anular los métodos estáticos, pero uno no debe malinterpretar el concepto de acceder a métodos estáticos desde la subclase .
Por ejemplo, vea el siguiente código: -
Salida:-
Gracias
fuente
El siguiente código muestra que es posible:
fuente
osm
es .OverridenStaticMeth
OverrideStaticMeth