Java: Default Methods
Default methods : O que é? E quando usar? Default Methods foi uma das novidades adicionadas na versão 8 do Java e possibilita flexibilizar bastante o uso de Interfaces. Para entender melhor a utilidade, é necessário que nós lembremos algumas "dores" em utilizar Interfaces. A Interface é um ótimo recurso quando precisamos definir um contrato e que este seja cumprido por quem o implementa. Até então é bem útil e faz com que a aplicação siga boas práticas de implementação. Mas caso precisamos criar um novo método em uma interface que já é implementada por diversas outras classes? Antes do Java 8, teríamos que implementar este novo método em todas estas classes para que o código não quebre e mesmo assim nem todas estas classes utilizaria este novo método. Lembrando que métodos de uma Interface são assinaturas de um contrato. Para entender melhor, vamos criar alguns exemplos simulando uma destas situações. Veja a Interface chamada CrudInterface public interface CrudInterface {
void create();
List<String> read();
void update();
void delete();
} O objetivo desta Interface é criar um contrato para classes que necessitem executar operações de CRUD ( C reate, R ead, U pdate e D elete) sigam o mesmo padrão de implementação. A seguir vamos criar duas classes que farão a implementação desta Interface. A classe UserDAO public class UserDAO implements CrudInterface {
@Override
public void create() {
System. out .println( "Create an User" );
}
@Override
public List<String> read() {
return Arrays. asList ( "user 1","user 2" );
}
@Override
public void update() {
System. out .println( "Update an User" );
}
@Override
public void delete() {
System. out .println( "Delete an User" );
}
} A classe ProductDAO public class ProductDAO implements CrudInterface {
@Override
public void create() {
System. out .println( "Create a Product" );
}
@Override
public List<String> read() {
return Arrays. asList ( "Product 1" , "Product 2" );
}
@Override
public void update() {
System. out .println( "Update a Product" );
}
@Override
public void delete() {
System. out .println( "Delete a Product" );
}
} As classes ProductDAO e UserDAO são obrigadas a implementar todos os métodos ou assinaturas declaradas na Interface CrudInterface . Apesar desta obrigatoriedade ter um lado positivo, que é manter um padrão de implementação, também possui um lado negativo, que é a não flexibilidade e uma possível quebra de código caso a Interface CrudInterface sofra alguma mudança futuramente. Imagine que além das classes ProductDAO e UserDAO , outras 20 classes também implementam a Interface CrudInterface . Cada vez mais o código está criando uma dependência. Agora, imagine que você precise adicionar um novo método na Interface CrudInterface que nem todas as classes que já implementam esta Interface vão utilizar. No cenário atual, teríamos que implementar este novo método em cada uma delas. Mas é aí que o recurso Default Methods entra pra nos ajudar. Para entender melhor, vamos supor que a classe UserDAO precise de um método que vai remover todos os usuário da base e que o time preferiu criar este novo método na interface CrudInterface pois poderia ser útil para as demais classes. Mas o time precisa garantir que esta alteração não quebre o código, ou seja, que o compilador não obrigue as classes implementarem este novo método. Vamos alterar a Interface CrudInterface utilizando Default Methods public interface CrudInterface {
void create();
List<String> read();
void update();
void delete();
default void deleteAll(){
System. out .println( "Delete all objects" );
}
} Adicionamos o método deleteAll( ) que supostamente será responsável por deletar todos os registros de uma entidade em específico. Perceba que é um método concreto dentro de uma Interface, que antes era utilizada apenas para declarar assinaturas abstratas. O ponto principal é a palavra chave default que assegura a utilização de Default Methods em uma Interface. Neste caso, não somos mais obrigados a implementar o método deleteAll( ) para todas as classes que implementam a Interface CrudInterface , ou seja, sem riscos de quebra o código. E por fim, possibilita a implementação de uma assinatura dentro da própria Interface. É claro que este é só uma forma de exemplificar a utilização de Default Methods , mas sugiro uma análise caso você precise criar um método que atenderá poucos cenários. Nem sempre a utilização de Interfaces seja a mais vantajosa. E aí, Curtiu? Até mais!