usar que gui definicion codigo java scala java-8 cake-pattern

que - swing java



¿Patrón de pastel con Java8 posible? (5)

Algunos experimentos sugieren que no:

  • Las clases anidadas son automáticamente estáticas. Esto es intrínsecamente incorpóreo:

    interface Car { class Engine { } } // ... Car car = new Car() { }; Car.Engine e = car.new Engine(); error: qualified new of static class Car.Engine e = car.new Engine();

  • Entonces, aparentemente, son interfaces anidadas, aunque es más difícil convencer a los mensajes de error:

    interface Car { interface Engine { } } // ... Car car = new Car() { }; class Yo implements car.Engine { } error: package car does not exist class Yo implements car.Engine { // ... class Yo implements Car.Engine { } // compiles ok.

Por lo tanto, sin las clases miembro de instancia, no tiene tipos dependientes de ruta, que son básicamente necesarios para el patrón de pastel. Así que al menos, no, no de una manera directa, no es posible.

Me pregunto: con Java 8, y la posibilidad de agregar implementación en interfaces (un poco como los rasgos de Scala), ¿será posible implementar el patrón de pastel , como podemos hacer en Scala?

Si es así, ¿puede alguien proporcionar un fragmento de código?


Con la inspiración de otras respuestas, se me ocurrió la siguiente jerarquía de clases (aproximada) que es similar al patrón de pastel en Scala:

interface UserRepository { String authenticate(String username, String password); } interface UserRepositoryComponent { UserRepository getUserRepository(); } interface UserServiceComponent extends UserRepositoryComponent { default UserService getUserService() { return new UserService(getUserRepository()); } } class UserService { private final UserRepository repository; UserService(UserRepository repository) { this.repository = repository; } String authenticate(String username, String password) { return repository.authenticate(username, password); } } interface LocalUserRepositoryComponent extends UserRepositoryComponent { default UserRepository getUserRepository() { return new UserRepository() { public String authenticate(String username, String password) { return "LocalAuthed"; } }; } } interface MongoUserRepositoryComponent extends UserRepositoryComponent { default UserRepository getUserRepository() { return new UserRepository() { public String authenticate(String username, String password) { return "MongoAuthed"; } }; } } class LocalApp implements UserServiceComponent, LocalUserRepositoryComponent {} class MongoApp implements UserServiceComponent, MongoUserRepositoryComponent {}

Lo anterior compila en Java 8 a partir del 9 de enero de 2013.

Entonces, ¿Java 8 puede hacer un patrón de pastel? Sí.

¿Es tan escueto como Scala, o tan efectivo como otros patrones en Java (es decir, inyección de dependencia)? Probablemente no, el boceto anterior requiere una gran cantidad de archivos y no es tan conciso como Scala.

En resumen:

  • Los auto-tipos (según sea necesario para el patrón de torta) se pueden emular extendiendo la interfaz base que esperamos.
  • Las interfaces no pueden tener clases internas (como lo señala @Owen), por lo tanto, podemos usar clases anónimas.
  • val y var pueden emularse utilizando un hashmap estático (y una inicialización perezosa), o el cliente de la clase simplemente almacena el valor de su lado (como lo hace UserService).
  • Podemos descubrir nuestro tipo usando this.getClass() en un método de interfaz predeterminado.
  • Como observa @Owen, los tipos dependientes de la ruta son imposibles de usar interfaces, por lo que un patrón de torta completa es inherentemente imposible. Lo anterior muestra, sin embargo, que uno podría usarlo para inyección de dependencia.

Hice una pequeña prueba de concepto recientemente. Puede ver la publicación del blog aquí: http://thoredge.blogspot.no/2013/01/cake-pattern-in-jdk8-evolve-beyond.html y el repositorio de github aquí: https://github.com/thoraage/cake-db-jdk8

Básicamente puedes hacerlo, pero te enfrentas al menos a dos obstáculos que lo hacen menos resbaladizo que Scala. En primer lugar, los rasgos de Scala pueden tener estado y la interfaz de Java no puede. Muchos módulos necesitan estado. Esto puede solucionarse creando un componente de estado general para mantener esta información, pero tendrá que estar en una clase. Al menos en parte. El segundo problema es que una clase anidada en una interfaz es más parecida a una clase anidada estática en clase. Por lo tanto, no puede acceder a los métodos de interfaz directamente desde la clase de módulo. El método de interfaz predeterminado tiene acceso a este ámbito y puede agregarlo al constructor de la clase de módulo.


Quizás puedas hacer algo como esto en Java 8.

interface DataSource { String lookup(long id); } interface RealDataSource extends DataSource { default String lookup(long id){ return "real#"+id; } } interface TestDataSource extends DataSource { default String lookup(long id){ return "test#"+id; } } abstract class App implements DataSource { void run(){ print( "data is " + lookup(42) ); } } class RealApp extends App implements RealDataSource {} new RealApp().run(); // prints "data is real#42" class TestApp extends App implements TestDataSource {} new TestApp().run(); // prints "data is test#42"

Pero de ninguna manera es mejor que el enfoque simple / antiguo.

interface DataSource { String lookup(long id); } class RealDataSource implements DataSource { String lookup(long id){ return "real#"+id; } } class TestDataSource implements DataSource { String lookup(long id){ return "test#"+id; } } class App { final DataSource ds; App(DataSource ds){ this.ds=ds; } void run(){ print( "data is " + ds.lookup(42) ); } } new App(new RealDataSource()).run(); // prints "data is real#42" new App(new TestDataSource()).run(); // prints "data is test#42"


Si ignora la nueva funcionalidad de Java 8, en teoría puede hacer el Cake Pattern en Java 5 y versiones superiores utilizando los ITJ de AspectJ de tiempo de compilación.

AspectJ DTO''s te permite hacer Mixins . Lo único molesto es que tendrás que hacer dos artefactos: el aspecto (ITD) y la interfaz. Sin embargo, los ITD te permiten hacer cosas locas como agregar anotaciones a las clases que implementan una interfaz.