Porque usar o abstract method e não uma outra classe?
Porque usar o abstract method e não uma outra classe?
Para ficar mais claro o uso do Abstract Method, posso te dar um exemplo onde ele é útil:
Vamos supor que você trabalhe um serviço de streaming como Globoplay, onde você terá no sistema uma classe chamada Globoplay para representar a assinatura
class Globoplay:
def get_valor(self):
return 20.0
Mas no Globoplay existem os combos, então você também pode assinar Globoplay + Disney, portanto no sistema você precisará criar uma classe assim:
class GloboplayComDisney:
def get_valor(self):
return Globoplay.get_valor() + 25.0
No Globoplay também existe o combo Globoplay + Disney + Deezer, portanto no sistema você precisará criar uma classe assim:
class GloboplayComDisneyComDeezer:
def get_valor(self):
return GloboplayComDisney.get_valor() + 15.0
Mas também é possível comprarmos os combos de Disney + Deezer, ou Globoplay + Deezer... Ou seja, as combinações de produtos são quase infinitas, isso acaba se tornando um problema para o nosso sistema, teremos um número muito grande de classes, e esses combos ficarão muito difíceis de manter, a forma como estamos fazendo o design da nossa aplicação vai prejudicar a manutenção, e nós podemos utilizar Abstract Method para melhor modelar nossa aplicação, dessa forma:
Teríamos uma classe abstrata:
from abc import ABC, abstractmethod
class Produto(ABC):
def __init__(self, outro_produto=None):
self.outro_produto = outro_produto
# Método abstrato que deve ser implementado pelas subclasses
@abstractmethod
def get_valor(self):
pass
# Método para obter o valor de outro produto
def get_valor_do_outro_produto(self):
if self.outro_produto is not None:
return self.outro_produto.get_valor()
return 0
E teríamos uma classe por produto, onde todas as classes herdariam da classe abstrata:
class Globoplay(Produto):
def __init__(self, outro_produto=None):
super().__init__(outro_produto)
def get_valor(self):
return 20.0 + self.get_valor_do_outro_produto()
class Disney(Produto):
def __init__(self, outro_produto=None):
super().__init__(outro_produto)
def get_valor(self):
return 25.0 + self.get_valor_do_outro_produto()
class Deezer(Produto):
def __init__(self, outro_produto=None):
super().__init__(outro_produto)
def get_valor(self):
return 15.0 + self.get_valor_do_outro_produto()
Assim, nossa classe principal ficaria dessa forma:
globoplay = Globoplay()
globoplay_com_disney = Globoplay(Disney())
globoplay_com_disney_com_deezer = Globoplay(Disney(Deezer()))
Nós não temos mais 1 classe para cada combo, nós temos 1 classe para cada produto, onde 1 produto pode compor-se com outro, um produto pode receber outro no construtor, a classe abstrata e o nosso abstract method garantem de fazer os cálculos dos valores pois todos os produtos implementam o método de get_valor
Essa estratégia se chama Decorator, um design pattern que utiliza Abstract Method para resolver problema onde classes podem ser compostas por elas mesmas