Inspirándome en otras respuestas se me ocurrió la siguiente jerarquía de clases (aproximada) que es similar al patrón del 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.
Así que, ¿puede Java 8 hacer un pastel- como ¿Patrón? Sí.
¿Es tan conciso como Scala, o tan eficaz como otros patrones en Java (por ejemplo, la inyección de dependencia)? Probablemente no, el boceto anterior requiere un montón de archivos y no es tan conciso como Scala.
En resumen:
- Los autotipos (necesarios para el patrón de la tarta) pueden emularse ampliando la interfaz base que esperamos.
- Las interfaces no pueden tener clases internas (como señala @Owen), así que en su lugar podemos utilizar clases anónimas.
val
y var
puede emularse utilizando un hashmap estático (e inicialización perezosa), o bien el cliente de la clase simplemente almacenando el valor en su lado (como hace UserService).
- Podemos descubrir nuestro tipo utilizando
this.getClass()
en un método de interfaz por defecto.
- Como señala @Owen, los tipos dependientes de la ruta son imposibles utilizando interfaces, por lo que un patrón de pastel completo es inherentemente imposible. Lo anterior muestra, sin embargo, que uno podría utilizarlo para la inyección de dependencia.