Criar um sistema simples para lidar com diferentes dispositivos de Entrada/Saída (I/O), como impressoras e monitores. O objetivo é ter uma função universal que possa enviar uma mensagem para qualquer dispositivo, desde que ele possua uma forma de escrever essa mensagem.
1. Crie a Interface Abstrata:
- Importe ABC e abstractmethod do módulo abc.
- Crie uma classe base abstrata chamada DispositivolO que herda de ABC .
- Defina um método abstrato chamado escrever(mensagem).
- Defina um método abstrato chamado ler() (que pode retornar uma string vazia por simplicidade, mas é necessário para a interface).
2. Crie Classes Concretas (Dispositivos):
- Crie a classe Impressora que herda de DispositivolO.
- Implemente escrever(mensagem) para imprimir: “IMPRESSORA: Imprimindo -> {mensagem}”.
- Implemente ler() para retornar: “Nenhuma entrada da impressora.”.
- Crie a classe Monitor que herda de DispositivolO.
- Implemente escrever(mensagem) para imprimir: “MONITOR: Exibindo na tela -> {mensagem}”.
- Implemente ler() para retornar: “Nenhuma entrada do monitor.”.
3. Função de Polimorfismo:
- Defina uma função chamada enviar_dados(dispositivo, dados) que aceita um objeto que esperamos ser um DispositivolO e uma string de dados.
- Dentro da função, chame dispositivo.escrever(dados).
- Opcionalmente, chame dispositivo.ler() e imprima o resultado para demonstrar a interface completa.
4. Teste:
- Crie instâncias de Impressora e Monitor.
- Chame a função enviar_dados para cada instância com uma mensagem diferente.
Passo 1
O enunciado pede que eu crie um pequeno sistema em Python que lide com diferentes dispositivos de Entrada/Saída (I/O) usando uma interface abstrata. As informações e requisitos fornecidos são:
- Importar
ABCeabstractmethoddo móduloabc. - Criar uma classe base abstrata chamada
DispositivolOque herda deABC. - Definir um método abstrato
escrever(mensagem). - Definir um método abstrato
ler()(pode retornar uma string vazia). - Criar a classe
Impressoraque herda deDispositivolO:escrever(mensagem)deve imprimir: “IMPRESSORA: Imprimindo -> {mensagem}”.ler()deve retornar: “Nenhuma entrada da impressora.”.
- Criar a classe
Monitorque herda deDispositivolO:escrever(mensagem)deve imprimir: “MONITOR: Exibindo na tela -> {mensagem}”.ler()deve retornar: “Nenhuma entrada do monitor.”.
- Definir a função
enviar_dados(dispositivo, dados)que:- Chama
dispositivo.escrever(dados). - Opcionalmente chama
dispositivo.ler()e imprime o resultado.
- Chama
- Testar criando instâncias de
ImpressoraeMonitore chamandoenviar_dadoscom mensagens diferentes.
Agora começo a implementação passo a passo, explicando cada conceito devagar e do jeito que dá pra entender na hora da prova.
Passo 2
Entendendo e implementando a interface abstrata (classe base):
-
Por que usar
ABCeabstractmethod?- Uma classe abstrata serve para definir um contrato: “todo dispositivo I/O deve ter estes métodos”. Isso nos força a implementar
escreverelernas classes concretas, e evita que alguém instancie a classe base diretamente. - Em Python usamos
from abc import ABC, abstractmethode marcamos métodos com@abstractmethod.
- Uma classe abstrata serve para definir um contrato: “todo dispositivo I/O deve ter estes métodos”. Isso nos força a implementar
-
Código da classe base
DispositivolO(explicação linha a linha):class DispositivolO(ABC):declara queDispositivolOé abstrata.@abstractmethodantes de um método diz que quem herdar precisa implementar esse método.def escrever(self, mensagem):assinatura do método que recebemensagem(uma string).def ler(self):assinatura do método que retorna uma string (pode ser vazia).
Exemplo de código (trecho):
from abc import ABC, abstractmethod
class DispositivolO(ABC):
@abstractmethod
def escrever(self, mensagem):
"""Escrever/Enviar uma mensagem para o dispositivo."""
pass
@abstractmethod
def ler(self):
"""Ler/Receber dados do dispositivo. Pode retornar string vazia."""
pass
Passo 3
Implementando a classe
Impressora:- O que é sobrescrever/override?
- Sobrescrever significa definir nas classes filhas a implementação concreta dos métodos abstratos da classe base.
Impressoraherda deDispositivolOe implementa os dois métodos obrigatórios.- Repare que
escrevervai usarprint()para mostrar a mensagem com o formato pedido. lerretorna a string fixa exigida.
Código (trecho) e explicação:
class Impressora(DispositivolO):
def escrever(self, mensagem):
# Aqui estamos implementando o comportamento real de "escrever" para a impressora.
print(f"IMPRESSORA: Imprimindo -> {mensagem}")
def ler(self):
# Impressoras normalmente não têm entrada para este exemplo.
return "Nenhuma entrada da impressora."
f"IMPRESSORA: Imprimindo -> {mensagem}"junta texto fixo com a variávelmensagem. Na prova, se não puder usar f-strings, pode usar concatenação ouformat, mas f-strings são claras.
Passo 4
Implementando a classe
Monitor:- Mesma ideia que a impressora: herda e implementa os métodos.
escreverexibe na tela com o formato pedido.lerretorna a string fixa correspondente.
Código (trecho):
class Monitor(DispositivolO):
def escrever(self, mensagem):
print(f"MONITOR: Exibindo na tela -> {mensagem}")
def ler(self):
return "Nenhuma entrada do monitor."
Passo 5
Criando a função polimórfica
enviar_dados e explicando polimorfismo:- Polimorfismo aqui significa que
enviar_dadosaceita qualquer objeto que implemente os métodos esperados (escrevereler). Não precisa saber se é impressora ou monitor — só chama os métodos. - Em Python isso segue o princípio do “duck typing”: se tem os métodos, funciona.
- A função deve:
- chamar
dispositivo.escrever(dados)para enviar a mensagem; - chamar
dispositivo.ler()e imprimir o retorno, mostrando que a interface está completa.
- chamar
Código:
def enviar_dados(dispositivo, dados):
"""
Envia dados para qualquer dispositivo que implemente os métodos
'escrever' e 'ler' (contrato definido por DispositivolO).
"""
dispositivo.escrever(dados)
resultado_leitura = dispositivo.ler()
print(f"Resultado de ler(): {resultado_leitura}")
Passo 6
Testando tudo junto (instâncias e chamadas):
- Criei instâncias de
ImpressoraeMonitor. - Chamei
enviar_dadospara cada uma com mensagens diferentes. - Mostro o trecho de teste e o que esperar como saída ao executar o script.
Código de teste:
if __name__ == "__main__":
imp = Impressora()
mon = Monitor()
enviar_dados(imp, "Relatório de vendas do mês")
enviar_dados(mon, "Bem-vindo ao painel de controle")
Saída esperada ao executar:
- Para a impressora:
IMPRESSORA: Imprimindo -> Relatório de vendas do mêsResultado de ler(): Nenhuma entrada da impressora.
- Para o monitor:
MONITOR: Exibindo na tela -> Bem-vindo ao painel de controleResultado de ler(): Nenhuma entrada do monitor.
Dica rápida para prova: se pedirem para adicionar um novo dispositivo (por exemplo,
Arquivo que escreve em disco), basta criar uma nova classe que herde DispositivolO e implementar escrever e ler. O restante do código (como enviar_dados) não precisa mudar — isso é o poder do polimorfismo.Passo 7
Pequenas observações práticas e incentivo:
- Se na prova pedirem para “mostrar a interface completa”, lembre de chamar tanto
escreverquantoler. - Se você esquecer
@abstractmethodna classe base, não terá a checagem automática e alguém poderá instanciar a classe base incorretamente. - Respira fundo: esse padrão (classe abstrata + implementação concreta + função que usa a interface) é muito comum — decorar esses passos ajuda a identificar o que a questão pede rapidamente.
Resposta
from abc import ABC, abstractmethod
class DispositivolO(ABC):
@abstractmethod
def escrever(self, mensagem):
"""Escrever/Enviar uma mensagem para o dispositivo."""
pass
@abstractmethod
def ler(self):
"""Ler/Receber dados do dispositivo. Pode retornar string vazia."""
pass
class Impressora(DispositivolO):
def escrever(self, mensagem):
print(f"IMPRESSORA: Imprimindo -> {mensagem}")
def ler(self):
return "Nenhuma entrada da impressora."
class Monitor(DispositivolO):
def escrever(self, mensagem):
print(f"MONITOR: Exibindo na tela -> {mensagem}")
def ler(self):
return "Nenhuma entrada do monitor."
def enviar_dados(dispositivo, dados):
dispositivo.escrever(dados)
resultado_leitura = dispositivo.ler()
print(f"Resultado de ler(): {resultado_leitura}")
if __name__ == "__main__":
imp = Impressora()
mon = Monitor()
enviar_dados(imp, "Relatório de vendas do mês")
enviar_dados(mon, "Bem-vindo ao painel de controle")