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 ABC e abstractmethod do módulo abc.
  • Criar uma classe base abstrata chamada DispositivolO que herda de ABC.
  • Definir um método abstrato escrever(mensagem).
  • Definir um método abstrato ler() (pode retornar uma string vazia).
  • Criar a classe Impressora que herda de DispositivolO:
    • escrever(mensagem) deve imprimir: “IMPRESSORA: Imprimindo -> {mensagem}”.
    • ler() deve retornar: “Nenhuma entrada da impressora.”.
  • Criar a classe Monitor que herda de DispositivolO:
    • 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.
  • Testar criando instâncias de Impressora e Monitor e chamando enviar_dados com 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 ABC e abstractmethod?
    • Uma classe abstrata serve para definir um contrato: “todo dispositivo I/O deve ter estes métodos”. Isso nos força a implementar escrever e ler nas classes concretas, e evita que alguém instancie a classe base diretamente.
    • Em Python usamos from abc import ABC, abstractmethod e marcamos métodos com @abstractmethod.
  • Código da classe base DispositivolO (explicação linha a linha):
    • class DispositivolO(ABC): declara que DispositivolO é abstrata.
    • @abstractmethod antes de um método diz que quem herdar precisa implementar esse método.
    • def escrever(self, mensagem): assinatura do método que recebe mensagem (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.
  • Impressora herda de DispositivolO e implementa os dois métodos obrigatórios.
  • Repare que escrever vai usar print() para mostrar a mensagem com o formato pedido.
  • ler retorna 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ável mensagem. Na prova, se não puder usar f-strings, pode usar concatenação ou format, mas f-strings são claras.

Passo 4

Implementando a classe Monitor:
  • Mesma ideia que a impressora: herda e implementa os métodos.
  • escrever exibe na tela com o formato pedido.
  • ler retorna 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_dados aceita qualquer objeto que implemente os métodos esperados (escrever e ler). 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.
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 Impressora e Monitor.
  • Chamei enviar_dados para 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ês
    • Resultado de ler(): Nenhuma entrada da impressora.
  • Para o monitor:
    • MONITOR: Exibindo na tela -> Bem-vindo ao painel de controle
    • Resultado 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 escrever quanto ler.
  • Se você esquecer @abstractmethod na 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")

Exercícios relacionados