java traços ou mixins padrão?
Pergunta
Existe uma maneira de imitar mixins ou traços em java? Basicamente, eu preciso de uma maneira de fazer herança múltipla para que eu possa adicionar lógica de negócios comuns a várias classes
Solução
Gostaria de encapsular toda a lógica de negócios para um novo BusinessLogic
classe e ter cada classe que precisa de chamadas BusinessLogic
make para a classe. Se você precisar de uma única hierarquia enraizada em suas classes que fazem chamadas para BusinessLogic
, você terá que criar uma interface bem (BusinessLogicInterface
?)
Em pseudo-código:
interface BusinessLogicInterace
{
void method1();
void method2();
}
class BusinessLogic implements BusinessLogicInterface
{
void method1() { ... }
void method2() { ... }
}
class User
extends OtherClass
implements BusinessLogicInterface
{
BusinessLogic logic = new BusinessLogic();
@Override
void method1() { logic.method1(); }
@Override
void method2() { logic.method2(); }
}
Esta não é a implementação mais bonita Para contornar a falta de herança múltipla e torna-se bastante complicado quando a interface tem um monte de métodos. Provavelmente, você vai querer experimentar e redesenhar o seu código para evitar a necessidade mixins.
Outras dicas
Não do jeito que você quiser fazê-lo. Effective Java recomenda que você "composição Favor sobre a herança". Ou seja, você mover a lógica comum a outras classes e delegado. Isto é como você contornar a falta de herança múltipla em Java.
É o objeto-purista mexendo em você hoje?
Pense que você poderia fazer com um pouco de programação orientada composite?
Então, senhor, está procurando Apache polygene (anteriormente Qi4J ou Zest);)
A resposta de Java a herança múltipla é a capacidade de implementar várias interfaces. Claro, isso significa que você vai ter as declarações de método, mas não a lógica.
Você poderia tentar emular mixins por composição:. Sua classe Java pode definir variáveis ??de membros que representam outras classes que executam alguma lógica de negócios comum
Na concepção de classes Java, eu não encontrei a falta de C ++ herança de estilo múltipla para inibir a concepção da minha arquitetura. Você vai encontrar uma maneira de conseguir o que você quer fazer.
QI4J permite mixins uso
Você pode explorar o fato de que as interfaces permitem classes aninhadas (automaticamente public static) para manter a implementação padrão dos métodos de interface encapsulados dentro da própria interface. Ou seja, mover a classe BusinessLogic do exemplo de Alex B dentro da interface.
Este é semelhante à maneira como Scala gera o código JVM para características como explicado aqui Como são traços Scala compilados em bytecode Java?
Ao fazer isso o exemplo torna-se:
interface BusinessLogicInterface {
void method0();
class DefaultImpl {
private DefaultImpl() {
}
public static void method1(BusinessLogicInterface self) { ... }
public static void method2(BusinessLogicInterface self) { ... }
}
void method1();
void method2();
}
class User extends OtherClass implements BusinessLogicInterface {
@Override
void method0() { ... }
@Override
void method1() { BusinessLogic.defaultImpl.method1(this); }
@Override
void method2() { BusinessLogic.defaultImpl.method2(this); }
}
Note que passar um objeto do tipo de interface como o parâmetro "self". Isto significa que a lógica de negócios pode usar outros métodos abstratos (method0). Isto pode ser muito útil para criar um traço com métodos abstratos que são todos ortogonais entre si e utilitário métodos de "extensão" que podem ser implementadas em termos de estes métodos ortogonais.
A desvantagem é que cada interface deve copiar / colar o código delegação clichê. Outro padrão frequentemente usado em Java sem esta desvantagem (mas com menos coesão e menos maneira OO para chamar os métodos) é criar uma classe com o nome plural como a interface que contém os métodos estáticos, isto é usado na classe de utilitário Collections.
Como de Java-8, foram adicionados métodos de interface padrão. Isto, juntamente com a herança múltipla de interfaces em Java deve permitir algum tipo de mixin. Claramente as interfaces têm a operar independentemente. Assim, haverá limitações significativas.