5.1 Trabalhando com livros digitais

Por causa da sua praticidade e fácil portabilidade, muitos leitores preferem livros digitais (e-books) aos livros físicos. Nossa livraria não pode ficar para trás, portanto, passaremos a trabalhar com esse novo tipo de livro.

Mas, afinal, como podemos diferenciar um Livro impresso de um Ebook? Uma forma simples de fazer isso seria adicionando um atributo que define o tipo de livro. Poderia simplesmente ser um boolean, marcando se um livro é impresso ou não. Repare:

public class Livro {
java
private String nome; private String descricao; private double valor;
 
private String isbn; private Autor autor; private boolean impresso;
 
public Livro(Autor autor) { this.autor autor;
 
this.isbn "000-00-00000-00-0"; this.impresso true;
 
}
 
// outros metodos da classe
 
}
 

Note que em nosso construtor já definimos um valor padrão para o atrib-

uto impresso. Todo Livro que não tenha o valor de impresso definido será considerado um livro impresso.

Essa é uma forma simples de resolver o problema e talvez até possa atender bem as nossas necessidades, mas o problema dessa abordagem é que um Ebook tem alguns comportamentos bastante diferentes do que um livro impresso. Por exemplo, o método aplicaDescontoDe da classe Livro atualmente limita a porcentagem de desconto em 30%.

public boolean aplicaDescontoDe(double porcentagem) { if (porcentagem > 0.3) {

return false;

}

this.valor - this.valor * porcentagem; return true;

}

Mas quando se trata de um Ebook, a regra é um pouco diferente: pode-

mos aplicar no máximo 15% de desconto. Podemos resolver esse problema adicionando mais uma condição ao método:

public boolean aplicaDescontoDe(double porcentagem) { if (porcentagem > 0.3) {

return false;

} else if (!this.impresso && porcentagem > 0.15) { return false;

}

this.valor — this.valor * porcentagem; return true;

}

Agora nosso código funciona como esperado, mas está um pouco mais

verboso e difícil de entender. O grande problema aqui é que, a cada método cuja regra seja diferente, teremos que colocar um novo if parecido com esse, isso sem contar que novos tipos de Livro podem aparecer e tornar nosso código ainda mais complicado e cheio de condicionais. Devemos sempre escrever nosso código pensando em como será sua evolução no futuro.

Além disso, existem alguns comportamentos e atributos que só servem para um Ebook. Um deles é o watermark (marca d’água). Essa é a forma de identificar discretamente o nome e e-mail do dono daquele livro digital, normalmente no rodapé das páginas.

Se Ebook é um elemento importante, possui comportamentos e atributos específicos, ele deveria ser representado como um Objeto! Podemos criar uma classe Ebook definindo os atributos e comportamentos específicos desse novo tipo.

public class Ebook {
java
private String nome; private String descricao; private double valor; private String isbn; private Autor autor; private String waterMark;
 
java
public void setWaterMark(String waterMark) { this.waterMark - waterMark;

}

public String getWaterMark() { return waterMark;

}

// getters, setters e outros metodos

}

Nosso código já está um pouco mais interessante, afinal não estamos mais

sobrecarregando a classe Livro com atributos e métodos que serão utilizados apenas quando o tipo do livro for um ebook. Mas há muito código repetido aqui: além dos comportamentos do Ebook, temos todos os atributos e métodos já escritos na classe Livro.

Para evitar toda essa repetição de código, podemos ensinar ao compilador que o Ebook é um tipo de Livro, ou seja, além de seus próprios atributos e métodos, essa classe possui tudo o que um Livro tem. Para fazer isto, basta Ebook dizer na declaração da classe que ela é um Livro, queé uma extensão dessa classe:

public class Ebook extends Livro { private String waterMark;
java
public Ebook(Autor autor) { super(autor);
 
}
 
java
public void setWaterMark(String waterMark) { this.waterMark = waterMark;

}

public String getWaterMark() { return waterMark;

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