Mesmo criaqndo a classe abstrata a minha aplicação executou, sem definir a classe abstrata na classe filha
C:\Caca\Alura\Python\DesignPatternsPython\ProjetoAPP>python calculador_de_impostos.py ISS e ICMS 50.0 30.0 ICPP e IKCV 25.0 30.0
C:\Caca\Alura\Python\DesignPatternsPython\ProjetoAPP>python calculador_de_impostos.py
# -*- coding: UTF-8 -*-
#impostos.py
#este import é utilizado para criação de classes abstratas
#toda classe abstrata tem que ter esta "meta" informação
from abc import ABCMeta, abstractmethod
#esta classe foi criada pra resolver o problema das classes ICPP e IKCN
#que tem regras semelhantes
class Template_de_imposto_condicional(object):
#classe abstrata
__metaclass__ = ABCMeta
def calcula(self, orcamento):
if self.deve_usar_maxima_taxacao(orcamento):
return self.maxima_taxacao(orcamento)
else:
return self.minima_taxacao(orcamento)
# o @abstractmethod faz com que a classe filha seja obrigada a implementar a classe abstrata
@abstractmethod
def deve_usar_maxima_taxacao(self, orcamento):
pass
@abstractmethod
def maxima_taxacao(self, orcamento):
pass
@abstractmethod
def minima_taxacao(self, orcamento):
pass
#o que antes era função agora vai virar classe
#def calculo_ISS(orcamento):
# return orcamento.valor * 0.1
#def calculo_ICMS(orcamento):
# return orcamento.valor * 0.06
class ISS(object):
def calcula(self, orcamento):
return orcamento.valor * 0.1
class ICMS(object):
def calcula(self, orcamento):
return orcamento.valor * 0.06
class ICPP(object):
def calcula(self, orcamento):
if orcamento.valor > 500:
return orcamento.valor * 0.07
else:
return orcamento.valor * 0.05
class IKCV(object):
def calcula(self, orcamento):
if orcamento.valor > 500 and self.__tem_item_maior_que_100_reais(orcamento):
return orcamento.valor * 0.01
else:
return orcamento.valor * 0.06
def __tem_item_maior_que_100_reais(self, orcamento):
for item in orcamento.obter_item():
if item.valor > 100:
return True
else:
return False
-----
# -*- coding: UTF-8 -*-
#calculo_de_imposto.py
from impostos import *
class Calculador_de_impostos(object):
#o parametro imposto passa a receber o nome da função que deve ser executaeda
def realiza_calculo(self, orcamento, imposto):
imposto_calculado = imposto.calcula(orcamento)
print imposto_calculado
#quando arquivo calculador_de_impostos.py for executado, no terminal do python
#todos os comandos embaixo do "if __name__ == '__main__':" serão executados
#este comando sera utilizado durante o curso para evitar a criação de classes para testar os métodos
if __name__ == '__main__':
#importando a classe Orcamento do arquivo orcamento.copyright
from orcamento import Orcamento, Item
calculador = Calculador_de_impostos()
orcamento = Orcamento()
orcamento.adiciona_item(Item('Item 1', 50.0))
orcamento.adiciona_item(Item('Item 2', 200.0))
orcamento.adiciona_item(Item('Item 3', 250.0))
print 'ISS e ICMS'
calculador.realiza_calculo(orcamento, ISS())
calculador.realiza_calculo(orcamento, ICMS())
print 'ICPP e IKCV'
calculador.realiza_calculo(orcamento, ICPP())
calculador.realiza_calculo(orcamento, IKCV())
-----
# -*- coding: UTF-8 -*-
# orcamento.py
class Orcamento(object):
def __init__(self):
self.__itens = []
# quando a propriedade for acessada, ela soma cada item retornando o valor do orçamento
@property
def valor(self):
total = 0.0
for item in self.__itens:
total+= item.valor
return total
# retornamos uma tupla, já que não faz sentido alterar os itens de um orçamento
def obter_itens(self):
return tuple(self.__itens)
# perguntamos para o orçamento o total de itens
@property
def total_itens(self):
return len(self.__itens)
def adiciona_item(self, item):
self.__itens.append(item)
# um item criado não pode ser alterado, suas propriedades são somente leitura
class Item(object):
def __init__(self, nome, valor):
self.__nome = nome
self.__valor = valor
@property
def valor(self):
return self.__valor
@property
def nome(self):
return self.__nome