7.1 O contrato Produto

Em Java, há uma outra forma para se tirar proveito de todos os benefícios do polimorfismo sem ter que acoplar tanto as suas classes com vários níveis de herança. Você pode estabelecer um fator em comum entre as classes, criando uma espécie de contrato.

Para esse contrato, não importa a forma como será implementado, a única coisa que importa é que seus métodos (cláusulas) sejam implementados de alguma forma. Isso lembra algo? Sim, é bastante parecido com um método abstrato cujo corpo você só define na superclasse para que todas as subclasses herdem a obrigação de implementá-lo.

Esse tipo de contrato Java é conhecido como Interface.

Não se trata de uma interface gráfica

É muito comum confundir no inicio, mas não estamos falando de uma interface gráfica de usuário (GUI). Também não estamos falando da interface da classe, seus métodos públicos. Você perceberá no decorrer do capítulo que se trata de um recurso diferente, um contrato Java.

Podemos criar uma interface Produto, que por enquanto terá um único método abstrato estabelecendo que todo produto deve ter o método

getValor. Uma interface se parece bastante com uma classe abstrata que tenha apenas métodos abstratos, mas no lugar de declará-la como uma classe, utilizamos a palavra reservada interface:

public interface Produto {
 
public abstract double getValor();
 
}
 

Como todo método sem corpo de uma interface é abstrato, o uso do mod-

ificador abstract é opcional. Não precisamos também adicionar o modificador public, pois seus métodos também são públicos por padrão. Podemos simplificar a escrita da interface Produto deixando apenas:

public interface Produto {
 
double getValor();
 
}
 

Uma interface não pode ter atributos e, até a versão 1.7 da linguagem, tam-

bém não pode ter nenhum método concreto, ou seja, com implementação. Veremos que, a partir do Java 1.8, isso mudou um pouco.

Podemos agora fazer com que todas as classes que idealizam produtos de nossa livraria assinem o contrato Produto. Para fazer isso, basta adicionar a palavra-chave implements seguida do nome da interface que deve ser implementada na declaração das classes, veja:

public abstract class Livro implements Produto {
 
// atributos e metodos omitidos
 
}
 
public class Revista implements Produto {

// atributos e metodos omitidos

}

Como todas essas classes já possuem o método getValor declarado,

você não perceberá nenhuma diferença. Nosso código passa a funcionar como esperado. Mas é importante perceber que se apagarmos o método

getValor a classe deixará de compilar, afinal toda classe que implementa a interface Produto é obrigada a implementar seus métodos abstratos.

Veja que com a interface o diagrama de nossas classes fica assim:

Como todos que implementam uma interface podem ser referenciados por este tipo, podemos usar polimorfismo com interfaces. Por exemplo, no método adiciona do CarrinhoDeCompras podemos receber um Produto como parâmetro:

public void adiciona(Produto produto) { System.out.println("Adicionando: " + produto); produto.aplicaDescontoDe(0.16);

total += produto.getValor();

}

O polimorfismo funcionará, mas o problema desse código é que nem todo

Produto tem o método aplicaDescontoDe, mas apenas os filhos da classe

Livro. Sim, poderíamos mover o método abstrato aplicaDescontoDe para a interface Produto, mas se nem todos os produtos têm um desconto, devemos evitar isso. Por enquanto, removeremos esse desconto, mas logo veremos uma forma mais interessante de resolver o problema. Nosso método deve ficar assim:

public void adiciona(Produto produto) { System.out.println("Adicionando: " + produto); total += produto.getValor();

}

Rode a classe RegistroDeVendas para ver que tudo está funcionando

como esperado. A classe continua assim:

public class RegistroDeVendas {
public static void main(String[] args) {

LivroFisico fisico = new livroFisico(autor); fisico.setNome(“Test-Driven Development”); fisico.setValor(59.90);

Ebook ebook = new Ebook(autor); ebook.setNome(“Test-Driven Development”); ebook.setValor(29.90);

CarrinhoDeCompras carrinho = new carrinhoDeCompras(); carrinho.adiciona(fisico);

carrinho.adiciona(ebook);

System.out.println("Total " + carrinho.getTotal());

⬅️ Capítulo Anterior | Próximo Capítulo ➡️