usar titledborder sirve settooltiptext setborder que password para como java enums strategy-pattern

titledborder - ¿Cómo usar los campos en enumeración de java anulando el método?



settooltiptext java para que sirve (8)

La tarea es implementar un patrón de diseño de estrategia hermoso con la enum java:

public enum MyEnum { FIRST { @Override public String doIt() { return "1: " + someField; //error } }, SECOND { @Override public String doIt() { return "2: " + someField; //error } }; private String someField; public abstract String doIt(); }

pero al referirme a someField obtengo

No se puede hacer una referencia estática al campo no estático someField.

¿Qué está mal y es posible hacerlo mejor?


Aparentemente el problema es que cuando dices:

public enum MyEnum { ... public abstract String doIt(); }

Necesita implícitamente que la enumeración sea una "clase" abstract , ya que debe proporcionarle una implementación. Por lo tanto, cuando dices

FIRST { @Override public String doIt() { return "1: " + this.someField; //error } }

Da un error porque está intentando acceder al campo privado de la "clase base" MyEnum , y como es privado, no es visible desde la subclase anónima creada implícitamente. Como tal, protected es visible desde la subclase, por lo tanto, soluciona el problema.

Hay algunas preguntas sobre Desbordamiento de pila que hablan sobre este problema, como Singletons, Enums y clases internas anónimas o ¿Por qué puedo subclasificar anónimamente una enumeración pero no una clase final? .

EDITAR: Aparentemente, no todo en esta declaración es correcto, porque mientras this.someField no funciona ya que el campo no es visible desde la subclase, se puede acceder a él como super.someField . Este es un fenómeno que no he visto antes, y trataré de analizarlo ahora.


Lo que podrías hacer es lo siguiente:

public enum MyEnum { FIRST,SECOND; private String someField; public String doIt(){ switch(this){ case FIRST: return "1: " + someField; break; case SECOND: return "2: " + someField; break; } } }

De esta manera, aún heredará Enum y puede usar MyEnum.values() y otras ventajas que provienen de derivar Enum .


Los campos privados no son accesibles desde las subclases, que es exactamente lo que haces cuando implementas el método abstracto MyEnum.doIt() en una base por instancia. Cambia a protected , y funcionará.


Si someField protegido en lugar de privado o usa super.someField , podrá acceder a él.


Una enum especializada no es más que una subclase con semántica de clase interna. Si observa el código de bytes después de la compilación, observará que el compilador solo inserta el método de acceso para leer un campo privado, pero cualquier enumeración especializada se compila como su propia clase. Puedes pensar que tu enum está implementando como:

public abstract class MyEnum { private static class First extends MyEnum { @Override public String doIt() { return "1: " + someField; //error } } private static class Second extends MyEnum { @Override public String doIt() { return "2: " + someField; //error } } public static final MyEnum FIRST = new First(); public static final MyEnum SECOND = new Second(); private String someField; public abstract String doIt(); }

Como puedes ver, ocurren los mismos errores del compilador. Efectivamente, su problema no se relaciona con las enum sino con su semántica de clase interna.

Sin embargo, encontró un caso límite en el que el compilador adivina la intención de su código y trata de advertirle que lo que pretende es ilegal. En general, el campo someField es visible para cualquier enum especializada. Sin embargo, hay dos formas de acceder al campo private desde una clase interna y solo una es legal:

  1. private miembros private no se heredan. Por lo tanto, no puede acceder a un campo private desde this instancia cuando se definió en una súper clase.

  2. Para las clases internas, los miembros de las clases externas son accesibles incluso si son private . Esto lo logra el compilador insertando métodos de acceso a las clases externas que exponen los campos private mediante métodos de acceso. Solo se puede acceder a un campo no static si la clase interna no es static . Para las enum , las clases internas son siempre static .

La condición posterior es de lo que se queja el compilador:

No se puede hacer una referencia estática al campo no estático someField

Está intentando acceder a un campo no static desde una clase interna static . Esto no es posible aunque el campo sea técnicamente visible debido a la semántica de la clase interna. Podría instruir al compilador explícitamente para que acceda al valor leyéndolo desde la súper clase, por ejemplo:

public String doIt() { MyEnum thiz = this; return thiz.someField; }

Ahora el compilador sabe que está intentando acceder a un miembro de un tipo visible (externo) en lugar de acceder erróneamente al campo someField de la instancia de la clase externa (no estática) (que no existe). (De manera similar, podría escribir super.someField que expresa la misma idea de que desea ir por la cadena de herencia y no acceder al campo de una instancia externa). Sin embargo, la solución más sencilla sería simplemente hacer que el campo esté protected . De esta manera, el compilador está contento con la visibilidad de la herencia y compila su configuración original.


Yo no implementaría el patrón de Estrategia utilizando una enumeración. Todo el código termina en la misma unti (archivo).

La idea es separar el código. Use una interfaz como clase base y luego implemente cada estrategia como una subclase separada. Agradable un limpio.


someField es una variable privada cuando las enumeraciones son variables estáticas. No puedes asignar una variable no estática a una variable estática de esta manera.


someField es privado, elimine el modificador privado o muévalo a sus clases abstractas.