resueltos metodos metodo interfaces ejercicios ejemplo definicion concepto clases clase abstractos abstracto abstractas abstracta java abstract-class static-methods

java - metodos - metodo abstracto ejemplo



¿Por qué los métodos estáticos no pueden ser abstractos en Java? (23)

La pregunta está en Java, ¿por qué no puedo definir un método estático abstracto? por ejemplo

abstract class foo { abstract void bar( ); // <-- this is ok abstract static void bar2(); //<-- this isn''t why? }


Creo que he encontrado la respuesta a esta pregunta, en la forma de por qué los métodos de una interfaz (que funcionan como métodos abstractos en una clase primaria) no pueden ser estáticos. Aquí está la respuesta completa (no la mía)

Básicamente, los métodos estáticos se pueden enlazar en tiempo de compilación, ya que para llamarlos se necesita especificar una clase. Esto es diferente de los métodos de instancia, para los cuales la clase de la referencia desde la cual está llamando el método puede ser desconocida en el momento de la compilación (por lo tanto, qué bloque de código se llama solo se puede determinar en el tiempo de ejecución).

Si está llamando a un método estático, ya conoce la clase donde se implementa, o cualquier subclase directa de él. Si usted define

abstract class Foo { abstract static void bar(); } class Foo2 { @Override static void bar() {} }

Entonces cualquier Foo.bar(); la llamada es obviamente ilegal, y siempre Foo2.bar(); .

Teniendo esto en cuenta, el único propósito de un método abstracto estático sería imponer subclases para implementar dicho método. Puede que inicialmente piense que esto es MUY incorrecto, pero si tiene un parámetro de tipo genérico <E extends MySuperClass> sería bueno garantizar a través de la interfaz que E puede .doSomething() . Tenga en cuenta que, debido al borrado de tipo, los genéricos solo existen en tiempo de compilación.

Entonces, ¿sería útil? Sí, y tal vez es por eso que Java 8 está permitiendo métodos estáticos en las interfaces (aunque solo con una implementación predeterminada). ¿Por qué no abstraer métodos estáticos con una implementación predeterminada en clases? Simplemente porque un método abstracto con una implementación predeterminada es en realidad un método concreto.

¿Por qué no métodos abstractos / interfaz estáticos sin implementación predeterminada? Aparentemente, simplemente por la forma en que Java identifica qué bloque de código debe ejecutar (la primera parte de mi respuesta).


Debido a que ''abstracto'' significa que el método está destinado a ser anulado y uno no puede anular los métodos ''estáticos''.


Debido a que abstracto es una palabra clave que se aplica sobre los métodos abstractos no se especifica un cuerpo. Y si hablamos de palabra clave estática pertenece a área de clase.


Diseño de mala lengua. Sería mucho más efectivo llamar directamente un método abstracto estático que crear una instancia solo para usar ese método abstracto. Especialmente cierto cuando se utiliza una clase abstracta como una solución para la enumeración que no se puede extender, que es otro ejemplo de diseño deficiente. Espero que resuelvan esas limitaciones en un próximo lanzamiento.


Este es un diseño de lenguaje terrible y realmente no hay razón para que no sea posible.

De hecho, aquí hay una implementación sobre cómo se puede hacer en JAVA :

public class Main { public static void main(String[] args) { // This is done once in your application, usually at startup Request.setRequest(new RequestImplementationOther()); Request.doSomething(); } public static final class RequestImplementationDefault extends Request { @Override void doSomethingImpl() { System.out.println("I am doing something AAAAAA"); } } public static final class RequestImplementaionOther extends Request { @Override void doSomethingImpl() { System.out.println("I am doing something BBBBBB"); } } // Static methods in here can be overriden public static abstract class Request { abstract void doSomethingImpl(); // Static method public static void doSomething() { getRequest().doSomethingImpl(); } private static Request request; private static Request getRequest() { // If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too. if ( request == null ) { return request = new RequestImplementationDefault(); } return request; } public static Request setRequest(Request r){ return request = r; } } }

================= Ejemplo anterior a continuación =================

Busque getRequest y getRequestImpl ... se puede llamar a setInstance para modificar la implementación antes de que se realice la llamada.

import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; /** * @author Mo. Joseph * @date 16 mar 2012 **/ public abstract class Core { // --------------------------------------------------------------- private static Core singleton; private static Core getInstance() { if ( singleton == null ) setInstance( new Core.CoreDefaultImpl() ); // See bottom for CoreDefaultImpl return singleton; } public static void setInstance(Core core) { Core.singleton = core; } // --------------------------------------------------------------- // Static public method public static HttpServletRequest getRequest() { return getInstance().getRequestImpl(); } // A new implementation would override this one and call setInstance above with that implementation instance protected abstract HttpServletRequest getRequestImpl(); // ============================ CLASSES ================================= // ====================================================================== // == Two example implementations, to alter getRequest() call behaviour // == getInstance() have to be called in all static methods for this to work // == static method getRequest is altered through implementation of getRequestImpl // ====================================================================== /** Static inner class CoreDefaultImpl */ public static class CoreDefaultImpl extends Core { protected HttpServletRequest getRequestImpl() { return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); } } /** Static inner class CoreTestImpl : Alternative implementation */ public static class CoreTestImpl extends Core { protected HttpServletRequest getRequestImpl() { return new MockedRequest(); } } }


La anotación abstract a un método indica que el método DEBE ser reemplazado en una subclase.

En Java, un miembro static (método o campo) no puede ser reemplazado por subclases (esto no es necesariamente cierto en otros lenguajes orientados a objetos, vea SmallTalk). Un miembro static puede estar oculto , pero eso es fundamentalmente diferente de lo que está invalidado .

Como los miembros estáticos no se pueden sobrescribir en una subclase, la anotación abstract no se puede aplicar a ellos.

Además, otros idiomas admiten la herencia estática, al igual que la herencia de instancia. Desde una perspectiva de sintaxis, esos idiomas generalmente requieren que el nombre de la clase se incluya en la declaración. Por ejemplo, en Java, suponiendo que está escribiendo código en ClassA, estas son declaraciones equivalentes (si methodA () es un método estático, y no hay un método de instancia con la misma firma):

ClassA.methodA();

y

methodA();

En SmallTalk, el nombre de la clase no es opcional, por lo que la sintaxis es (tenga en cuenta que SmallTalk no usa el. Para separar el "sujeto" y el "verbo", sino que lo usa como el terminador de la premisa):

ClassA methodA.

Debido a que el nombre de la clase siempre es obligatorio, la "versión" correcta del método siempre se puede determinar al atravesar la jerarquía de clases. Por lo que vale, a veces echo de menos static herencia static , y me mordió la falta de herencia estática en Java cuando comencé con ella. Además, SmallTalk está tipificado como pato (y por lo tanto no es compatible con el programa por contrato). Por lo tanto, no tiene un modificador abstract para los miembros de la clase.


La idea de tener un método estático abstracto sería que no puede usar esa clase abstracta en particular directamente para ese método, pero solo a la primera derivada se le permitirá implementar ese método estático (o para los genéricos: la clase real del genérico que usted utiliza). utilizar).

De esa manera, podría crear, por ejemplo, una clase abstracta sortableObject o incluso una interfaz con métodos estáticos abstractos (auto), que definen los parámetros de las opciones de clasificación:

public interface SortableObject { public [abstract] static String [] getSortableTypes(); public String getSortableValueByType(String type); }

Ahora puede definir un objeto clasificable que puede ordenarse por los tipos principales que son los mismos para todos estos objetos:

public class MyDataObject implements SortableObject { final static String [] SORT_TYPES = { "Name","Date of Birth" } static long newDataIndex = 0L ; String fullName ; String sortableDate ; long dataIndex = -1L ; public MyDataObject(String name, int year, int month, int day) { if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed."); if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date."); this.fullName = name ; this.sortableDate = MyUtils.createSortableDate(year,month,day); this.dataIndex = MyDataObject.newDataIndex++ ; } public String toString() { return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")"; } // override SortableObject public static String [] getSortableTypes() { return SORT_TYPES ; } public String getSortableValueByType(String type) { int index = MyUtils.getStringArrayIndex(SORT_TYPES, type); switch(index) { case 0: return this.name ; case 1: return this.sortableDate ; } return toString(); // in the order they were created when compared } }

Ahora puedes crear un

public class SortableList<T extends SortableObject>

que puede recuperar los tipos, crear un menú emergente para seleccionar un tipo para ordenar y recurrir a la lista obteniendo los datos de ese tipo, así como tener una función de adición que, cuando se ha seleccionado un tipo de clasificación, puede auto -Ordenar nuevos elementos. Tenga en cuenta que la instancia de SortableList puede acceder directamente al método estático de "T":

String [] MenuItems = T.getSortableTypes();

El problema de tener que usar una instancia es que SortableList puede no tener elementos todavía, pero ya debe proporcionar la clasificación preferida.

Cheerio, Olaf.


Los métodos regulares pueden ser abstractos cuando están destinados a ser reemplazados por subclases y provistos de funcionalidad. Imagine que la clase Foo se extiende por Bar1, Bar2, Bar3 etc. Entonces, cada uno tendrá su propia versión de la clase abstracta según sus necesidades.

Ahora, los métodos estáticos, por definición, pertenecen a la clase, no tienen nada que ver con los objetos de la clase o los objetos de sus subclases. Ni siquiera necesitan que existan, se pueden usar sin crear instancias de las clases. Por lo tanto, deben estar listos para el uso y no pueden depender de las subclases para agregarles funcionalidad.


No se puede anular un método estático, por lo que hacerlo abstracto no tendría sentido. Además, un método estático en una clase abstracta pertenecería a esa clase, y no a la clase dominante, por lo que no podría usarse de todos modos.


Porque "abstracto" significa: "No implementa ninguna funcionalidad", y "estático" significa: "Hay funcionalidad incluso si no tiene una instancia de objeto". Y eso es una contradicción lógica.


Primero, un punto clave sobre las clases abstractas: no se puede crear una instancia de una clase abstracta (ver wiki ). Por lo tanto, no se puede crear ninguna instancia de una clase abstracta.

Ahora, la forma en que java trata con los métodos estáticos es compartiendo el método con todas las instancias de esa clase.

Por lo tanto, si no puede crear una instancia de una clase, esa clase no puede tener métodos estáticos abstractos ya que un método abstracto pide ser extendido.

Auge.


Puedes hacer esto con interfaces en Java 8.

Esta es la documentación oficial al respecto:

doc


Se puede llamar a un método estático sin una instancia de la clase. En su ejemplo, puede llamar a foo.bar2 (), pero no a foo.bar (), porque para la barra necesita una instancia. El siguiente código funcionaría:

foo var = new ImplementsFoo(); var.bar();

Si llama a un método estático, se ejecutará siempre el mismo código. En el ejemplo anterior, incluso si redefine bar2 en ImplementsFoo, una llamada a var.bar2 () ejecutaría foo.bar2 ().

Si bar2 ahora no tiene implementación (eso es lo que significa abstracto), puede llamar a un método sin implementación. Eso es muy dañino.


Según el doc Java:

Un método estático es un método que está asociado con la clase en la que se define en lugar de con cualquier objeto. Cada instancia de la clase comparte sus métodos estáticos.

En Java 8, junto con los métodos predeterminados, también se permiten métodos estáticos en una interfaz. Esto nos facilita la organización de métodos de ayuda en nuestras bibliotecas. Podemos mantener métodos estáticos específicos para una interfaz en la misma interfaz en lugar de en una clase separada.

Un buen ejemplo de esto es:

list.sort(ordering);

en lugar de

Collections.sort(list, ordering);

Otro ejemplo de uso de métodos estáticos también se da en el propio doc :

public interface TimeClient { // ... static public ZoneId getZoneId (String zoneString) { try { return ZoneId.of(zoneString); } catch (DateTimeException e) { System.err.println("Invalid time zone: " + zoneString + "; using default time zone instead."); return ZoneId.systemDefault(); } } default public ZonedDateTime getZonedDateTime(String zoneString) { return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString)); } }


Supongamos que hay dos clases, Parent e Child . Parent es abstract . Las declaraciones son las siguientes:

abstract class Parent { abstract void run(); } class Child extends Parent { void run() {} }

Esto significa que cualquier instancia de Parent debe especificar cómo se run() .

Sin embargo, supongamos ahora que Parent no es abstract .

class Parent { static void run() {} }

Esto significa que Parent.run() ejecutará el método estático.

La definición de un método abstract es "Un método que se declara pero no se implementa", lo que significa que no devuelve nada por sí mismo.

La definición de un método static es "Un método que devuelve el mismo valor para los mismos parámetros independientemente de la instancia en la que se llama".

El valor de retorno de un método abstract cambiará a medida que cambie la instancia. Un método static no lo hará. Un método static abstract es más o menos un método donde el valor de retorno es constante, pero no devuelve nada. Esta es una contradicción lógica.

Además, realmente no hay muchas razones para un método static abstract .


También hice la misma pregunta, aquí es por qué

Como dice la clase Abstract, no dará implementación y permitirá que la subclase le dé

así que Subclase tiene que anular los métodos de Superclase,

REGLA NO 1 - Un método estático no puede ser anulado

Debido a que los miembros y los métodos estáticos son elementos de tiempo de compilación, es por eso que se permite la sobrecarga (Polimorfismo de tiempo de compilación) de los métodos estáticos en lugar de la Anulación (Polimorfismo de tiempo de ejecución)

Por lo tanto, no pueden ser abstractos.

No hay nada como el resumen estático <--- No permitido en el Universo Java


Un método estático, por definición, no necesita saber this . Por lo tanto, no puede ser un método virtual (que se sobrecarga según la información de subclase dinámica disponible a través de this ); en su lugar, una sobrecarga del método estático se basa únicamente en la información disponible en el momento de la compilación (esto significa: una vez que se refiere un método estático de superclase, se llama el método superclase, pero nunca un método de subclase).

De acuerdo con esto, los métodos estáticos abstractos serían bastante inútiles porque nunca se sustituirá su referencia por algún cuerpo definido.


Una clase abstracta no puede tener un método estático porque la abstracción se realiza para lograr la vinculación dinámica, mientras que los métodos estáticos están vinculados estáticamente a su funcionalidad. Un método estático significa que el comportamiento no depende de una variable de instancia, por lo que no se requiere ninguna instancia / objeto. Solo la clase. Los métodos estáticos pertenecen a la clase y no al objeto. Se almacenan en un área de memoria conocida como PERMGEN desde donde se comparte con cada objeto. Los métodos en clase abstracta están vinculados dinámicamente a su funcionalidad.


Veo que ya hay un gran número de respuestas, pero no veo ninguna solución práctica. Por supuesto, este es un problema real y no hay una buena razón para excluir esta sintaxis en Java. Dado que la pregunta original carece de un contexto donde esto pueda ser necesario, proporciono un contexto y una solución:

Supongamos que tiene un método estático en un grupo de clases que son idénticas. Estos métodos llaman a un método estático que es específico de la clase:

class C1 { static void doWork() { ... for (int k: list) doMoreWork(k); ... } private static void doMoreWork(int k) { // code specific to class C1 } } class C2 { static void doWork() { ... for (int k: list) doMoreWork(k); ... } private static void doMoreWork(int k) { // code specific to class C2 } }

doWork() métodos doWork() en C1 y C2 son idénticos. Puede haber muchos de estos calsses: C3 C4 etc. Si se permitiera el static abstract , eliminaría el código duplicado haciendo algo como:

abstract class C { static void doWork() { ... for (int k: list) doMoreWork(k); ... } static abstract void doMoreWork(int k); } class C1 extends C { private static void doMoreWork(int k) { // code for class C1 } } class C2 extends C { private static void doMoreWork(int k) { // code for class C2 } }

pero esto no se compilaría porque static abstract combinación static abstract no está permitida. Sin embargo, esto se puede sortear con static class construcción de static class , que se permite:

abstract class C { void doWork() { ... for (int k: list) doMoreWork(k); ... } abstract void doMoreWork(int k); } class C1 { private static final C c = new C(){ @Override void doMoreWork(int k) { System.out.println("code for C1"); } }; public static void doWork() { c.doWork(); } } class C2 { private static final C c = new C() { @Override void doMoreWork(int k) { System.out.println("code for C2"); } }; public static void doWork() { c.doWork(); } }

Con esta solución el único código que está duplicado es

public static void doWork() { c.doWork(); }


porque si está utilizando cualquier miembro estático o variable estática en la clase, se cargará en el momento de carga de la clase.


Declarar un método que staticsignifica que podemos llamar a ese método por su nombre de clase y si esa clase es abstractasí, no tiene sentido llamarlo, ya que no contiene ningún cuerpo, y por lo tanto no podemos declarar un método tanto como staticy abstract.


Porque si una clase extiende una clase abstracta, entonces tiene que anular los métodos abstractos y eso es obligatorio. Y dado que los métodos estáticos son métodos de clase resueltos en tiempo de compilación, mientras que los métodos sobrescritos son métodos de instancia resueltos en tiempo de ejecución y siguiendo el polimorfismo dinámico.


  • Un método abstracto se define solo para que pueda ser anulado en una subclase. Sin embargo, los métodos estáticos no pueden ser anulados. Por lo tanto, es un error en tiempo de compilación tener un método abstracto y estático.

    Ahora la siguiente pregunta es ¿por qué los métodos estáticos no pueden ser anulados?

  • Es porque los métodos estáticos pertenecen a una clase particular y no a su instancia. Si intenta anular un método estático, no obtendrá ningún error de compilación o tiempo de ejecución, pero el compilador simplemente ocultará el método estático de superclase.