12.6 (Opcional) Exercícios - Interfaces E Classes Abstratas
- Nosso banco precisa tributar dinheiro de alguns bens que nossos clientes possuem. Para isso, vamos criar uma classe Tributavel no módulo tributavel.py, e adicionar um método que devolve o imposto sobre a conta:
class Tributavel:
python
def get_valor_imposto(self): pass
Lemos essa classe da seguinte maneira: “todos que quiserem ser tributáveis precisam saber retornar o valor do imposto”. Alguns bens são tributáveis e outros não, ContaPoupanca não é tributável, já para ContaCorrente você precisa pagar 1% da conta e o SeguroDeVida tem uma faixa fixa de 50 reais mais 5% do valor do seguro.
- Torne a classe Tributavel uma classe abstrata:
import abc
python
class Tributavel(abc.ABC):
python
def get_valor_imposto(self) pass
3. O método get_valor_imposto() também deve ser abstrato:
python
import abc
python
class Tributavel(abc.ABC):@abc.abstractmethod
def get_valor_imposto(self, valor): pass
- Nada impede que os usuários de nossa classe tributavel implementem o método get_valor_imposto de maneira não esperada por nós. Então, vamos acrescentar a documentação utilizando docstring que aprendemos no capítulo de módulos:
import abc
python
class Tributavel(abc.ABC):""" Classe que contém operações de um objeto autenticável
As subclasses concretas devem sobrescrever o método get_valor_imposto. """
@abc.abstractmethod
def get_valor_imposto(self):
""" aplica taxa de imposto sobre um determinado valor do objeto """ pass
-
Utiliza a função help() passando a classe Tributavel para acessar a documentação.
-
Faça a classe ContaCorrente herdar da classe Tributavel :
class ContaCorrente(Conta, Tributavel): # código omitido
python
def get_valor_imposto(self): return self._saldo \* 0.01
7. Crie a classe SeguroDeVida , com os atributos valor , titular e numero_apolice , que também deve ser um tributável. Implemente o método get_valor_imposto() de acordo com a regra de negócio definida pelo exercício:
python
class SeguroDeVida(Tributavel):
python
def __init__(self, valor, titular, numero_apolice): self._valor = valor
self._titular = titular self._numero_apolice = numero_apolice
def get_valor_imposto(self): return 50 + self._valor \* 0.05
8. Vamos criar a classe ManipuladorDeTributaveis em um arquivo chamado *manipulador_tributaveis.py*. Essa classe deve ter um método chamado calcula_impostos() que recebe umas lista de tributáveis e retorna o total de impostos cobrados:
python
class ManipuladorDeTributaveis:
python
def calcula_impostos(self, lista_tributaveis): total = 0
for t in lista_tributaveis:
total += t.get_valor_imposto()
return total
- Nossas classes ContaCorrente e SeguroDeVida já implementam o método
get_valor_imposto() . Vamos instanciar cada umas delas e testar a chamada do método:
if name == ' main ':cc = ContaCorrente(‘123-4’, ‘João’, 1000.0) seguro = SeguroDeVida(100.0, ‘José’, ‘345-77’)
print(cc.get_valor_imposto()) print(seguro.get_valor_imposto())- Crie uma lista com os objetos criados no exercício anterior, instancie um objeto do tipo list e passe a lista chamando o método calcula_impostos() .
if name == ' main ':código omitido
lista_tributaveis = [] lista_tributaveis.append(cc) lista_tributaveis.append(seguro)
mt = ManipuladorDeTributaveis()
total = mt.calcula_impostos(lista_tributaveis) print(total)
- Nosso código funciona, mas ainda estamos utilizando herança múltipla! Vamos melhorar nosso código. Faça com que ContaCorrente e SeguroDeVida não mais herdem da classe Tributavel :
class ContaCorrente(Conta): # código omitido
python
class SeguroDeVida: # código omitidoVamos registrar nossas classes ContaCorrente e SeguroDeVida como subclasses virtuais de
Tributavel , de modo que funcione como uma interface.
if name == ' main ':
python
from tributavel import Tributavelcc = ContaCorrente(‘João’, ‘123-4’) cc.deposita(1000.0)
seguro = SeguroDeVida(100.0, ‘José’, ‘345-77’)
Tributavel.register(ContaCorrente) Tributavel.register(SeguroDeVida)
lista_tributaveis = [] lista_tributaveis.append(cc) lista_tributaveis.append(seguro)
mt = ManipuladorDeTributaveis()
total = mt.calcula_impostos(lista_tributaveis) print(total)
- Modifique o método calcula_impostos() da classe ManipuladorDeTributaveis para checar se os elementos da listas são tributáveis através do método isinstance() . Caso um objeto da lista não seja um tributável, vamos imprimir uma mensagem de erro e apenas os tributáveis serão somados ao total:
class ManipuladorDeTributaveis:
python
def calcula_impostos(self, lista_tributaveis): total = 0
for t in lista_tributaveis:
if (isinstance(t, Tributavel)): total += t.get_valor_imposto()
else:
java
print(t. repr (), "não é um tributável") return totalTeste novamente com a lista de tributáveis que fizemos no exercício anterior e veja se tudo continua funcionando.
- ContaPoupanca não é um tributável. Experimente instanciar uma ContaPoupanca , adicionar a lista de tributáveis e calcular o total de impostos através do ManipuladorDeTributaveis :
if name == ' main ':código omitido do exercício anterior omitido
cp = ContaPoupanca(‘123-6’, ‘Maria’) lista_tributaveis.append(cp)
total = mt.calcula_impostos(lista_tributaveis) print(total)
O que acontece?
- (Opcional) Agora, além de ContaCorrente e SeguroDeVida , nossa ContaInvestimento
também deve ser um tributável, cobrando 3% do saldo. Instancie uma ContaInvestimento .
class ContaInvestimento(Conta): def atualiza(self, taxa):self._saldo += self._saldo * taxa *
def get_valor_imposto(self): return self._saldo \* 0.03
Registre a classe ContaInvestimento como tributável. Adicione a ContaInvestimento criada na lista de tributáveis do exercício anterior e calcule o total de impostos através do ManipuladorDeTributaveis .
if name == " main ": # código omitidoci = ContaInvestimento(‘Ana’, ‘123-0’) ci.deposita(100.0) Tributavel.register(ContaInvestimento)
lista_tributaveis.append(ci) mt = ManipuladorDeTributaveis()
total = mt.calcula_impostos(lista_tributaveis) print(total)
Neste capítulo, aprendemos sobre herança múltipla e suas desvantagens mesmo utilizando mix-ins. Além disso, aprendemos a utilizar classes abstratas como interfaces registrando as classes e evitando os problemas com a herança múltipla. Agora nossa classe abstrata Tributavel funciona como um protocolo. No capítulo sobre o módulo collections, veremos na prática alguns conceitos vistos neste capítulo.
CAPÍTULO 13