Olá, Luiz Fernando. Como vai?
Parabéns pela resolução da atividade! O seu código está excelente e demonstra uma compreensão muito sólida sobre os pilares da Orientação a Objetos em Python, especialmente no uso de Herança, Polimorfismo e o reaproveitamento de código com o método super().
A forma como você utilizou o método especial __str__ nas duas classes ficou impecável. No arquivo carro.py, ao chamar super().__str__(), você evitou a repetição desnecessária de código e garantiu que o carro aproveitasse a formatação base da marca e do modelo criada na classe mãe, adicionando apenas o atributo específico (cor). Essa é a legítima elegância do paradigma focado em objetos.
Como um bom par de programação, quero analisar com você dois pontos importantes do seu código: um pequeno erro de sintaxe que pode quebrar a execução dependendo da versão do Python, e um detalhe conceitual sobre Classes Abstratas que é muito cobrado no mercado.
1. O Ajuste de Sintaxe (Recuo do Decorador)
No seu arquivo veiculo.py, o decorador @abstractmethod e a assinatura do método ligar acabaram ficando com um recuo (indentação) desalinhado. No Python, a indentação define o escopo.
Se o decorador estiver empurrado para a direita, o interpretador vai gerar um erro de indentação (IndentationError). O alinhamento correto dentro da classe deve ser este:
def __str__(self):
return f"Marca: {self.marca} | Modelo: {self.modelo} | Estado: {'Ligado' if self._ligado else 'Desligado'}"
@abstractmethod
def ligar(self):
self._ligado = True
print(f"{self.modelo} Ligado.")
Dica extra: Repare que dentro da f-string do __str__, eu alterei as aspas duplas do {"Ligado" if ...} para aspas simples {'Ligado' if ...}. Usar o mesmo tipo de aspas dentro e fora da f-string costuma confundir o Python em algumas versões.
2. O Conceito de Método Abstrato com Implementação
O seu método ligar em Veiculo foi marcado com @abstractmethod, mas você colocou um corpo de código dentro dele (mudando o estado para True e dando um print). E no seu Carro, você chamou esse comportamento usando super().ligar().
O código funciona? Sim, o Python permite de forma legítima que um método abstrato tenha uma implementação base que pode ser herdada pelas classes filhas através do super().
Onde está o ponto de atenção conceitual? No design de software, quando definimos um método como abstrato, a nossa intenção principal é criar um contrato puro. Estamos dizendo: "Eu não sei COMO um veículo liga (afinal, um carro liga com a chave, uma moto no pedal e um barco puxando uma corda), mas eu obrigo qualquer classe filha a criar a sua própria lógica de ligar".
Se a classe mãe já sabe exatamente o que o método faz (mudar a variável _ligado para True), o mais recomendado conceitualmente seria manter o método ligar como um método concreto comum na classe mãe.
Veja a diferença das duas abordagens de mercado:
- Abordagem A (Método Concreto Comum): Se todos os veículos ligam do mesmo jeito (apenas alterando o atributo
_ligado), remova o @abstractmethod. Assim, a classe Carro nem precisará reescrever o método ligar, ela já herda o comportamento automaticamente. O seu arquivo main.py funcionará sem você precisar digitar a função ligar em cada classe filha. - Abordagem B (Contrato Abstrato Puro): Se cada veículo liga de um jeito único, o método na classe mãe deve apenas ditar a regra, usando
pass:
# Em veiculo.py
@abstractmethod
def ligar(self):
pass
# Em carro.py
def ligar(self):
print(f"Ligando o carro {self.modelo} através da chave...")
self._ligado = True # O carro resolve como altera o próprio estado
A sua solução prática está muito bem estruturada, e ver você aplicando herança com super() logo no início dos estudos mostra que você tem muita facilidade com a lógica de POO.
Corrigindo o detalhe do alinhamento do decorador, o seu projeto está pronto para rodar perfeitamente e consumir qualquer API! Continue com essa constância fantástica.
Espero que possa ter lhe ajudado!