from abc import ABC, abstractmethod
class IState(ABC):
"""Interface para o padrão de projeto State."""
@abstractmethod
def sucesso_ao_pagar(self) -> None:
pass
@abstractmethod
def despachar_pedido(self) -> None:
pass
@abstractmethod
def cancelar_pedido(self) -> None:
pass
class Pedido:
"""Classe que representa um pedido."""
def __init__(self) -> None:
self.estado_atual = AguardandoPagamentoState(self)
def realizar_pagamento(self) -> None:
self.estado_atual.sucesso_ao_pagar()
def despachar(self) -> None:
self.estado_atual.despachar_pedido()
def cancelar(self) -> None:
self.estado_atual.cancelar_pedido()
def set_estado_atual(self, estado_atual: IState) -> None:
self.estado_atual = estado_atual
def __str__(self) -> str:
return str(self.estado_atual)
class AguardandoPagamentoState(IState):
"""Estado inicial do pedido."""
def __init__(self, meu_pedido: Pedido):
self.pedido = meu_pedido
def sucesso_ao_pagar(self) -> None:
print("Pedido pago com sucesso!")
self.pedido.set_estado_atual(PagoState(self.pedido))
def despachar_pedido(self) -> None:
print("Pedido não pode ser despachado, pois não foi pago!")
def cancelar_pedido(self) -> None:
print("Pedido cancelado com sucesso!")
self.pedido.set_estado_atual(CanceladoState(self.pedido))
This code works fine, but when i run mypy, it states:
Incompatible types in assignment (expression has type "IState", variable has type "AguardandoPagamentoState") [assignment]mypy
Why is it generating this problem, given that the AguardandoPagamentoState class implements the IState interface?
If I put a comment like
# type: ignore
it stops throwing this error, but I want to know how solve this. Mypy should understand the class relation
The problem is that you establish a static type of AguardandoPagamentoState
for the attribute in Pedido.__init__
:
def __init__(self) -> None:
self.estado_atual = AguardandoPagamentoState(self)
But then you try to relax that by allowing any value of type IState
to be assigned to it in set_estado_atual
:
def set_estado_atual(self, estado_atual: IState) -> None:
self.estado_atual = estado_atual
AguardandoPagamentoState
may implement the interface, but not all types that implement the interface are AguardandoPagamentoState
or subclasses thereof. You need to establish the more general static type explicitly:
def __init__(self) -> None:
self.estado_atual: IState = AguardandoPagamentoState(self)