Lista 02 - Classes e Objetos
Lista 02 - Classes e Objetos
Seção intitulada “Lista 02 - Classes e Objetos”Lista de exercícios sobre Orientações a Objetos em Python. Você foi contratado(a) como dev júnior da Byte Games, um estúdio de jogos mobile que está dando seus primeiros passos. A cada nível, uma nova missão dentro do estúdio: modelar classes, escrever construtores, criar métodos e proteger os dados dos seus sistemas. Resolva os exercícios em ordem, cada nível constrói a base para o próximo.
Nível 1: Criação e Instanciação de Classes
Seção intitulada “Nível 1: Criação e Instanciação de Classes”Nesta missão você vai trabalhar com a classe modelo dos sistemas do estúdio, criando objetos a partir dela.
Exercício 1.1: Fábrica de Karts (Programação)
Seção intitulada “Exercício 1.1: Fábrica de Karts (Programação)”Competência: Criação de objetos a partir de uma classe, acesso a atributos e chamada de métodos.
Contexto:
O estúdio prepara um arcade de corrida estilo kart. O time de gameplay já definiu a classe Kart e a colou no código abaixo. Seu papel é usar essa classe para cadastrar os três pilotos confirmados do jogo e colocá-los na pista.
Classe fornecida:
class Kart: def __init__(self, piloto, cor): self.piloto = piloto self.cor = cor
def acelerar(self): print(f"{self.piloto} acelerou o kart {self.cor}!")
def derrapar(self): print(f"{self.piloto} derrapou na curva!")Instruções:
- Crie três objetos da classe
Kart, um para cada piloto, com os dados abaixo:Mario, kart vermelho;Luigi, kart verde;Peach, kart rosa.
- Imprima o nome do piloto e a cor de cada kart, um por linha.
- Chame o método
acelerar()no kart doMarioe o métododerrapar()no kart daPeach.
Saída esperada:
Mario pilota o kart vermelho.Luigi pilota o kart verde.Peach pilota o kart rosa.Mario acelerou o kart vermelho!Peach derrapou na curva!Exercício 1.2: Recrutando o Inimigo (Múltipla escolha)
Seção intitulada “Exercício 1.2: Recrutando o Inimigo (Múltipla escolha)”Competência: Sintaxe correta para instanciar objetos.
Contexto:
No novo jogo de terror do estúdio, a classe Inimigo já está pronta:
class Inimigo: def __init__(self, nome, vida): self.nome = nome self.vida = vida
def atacar(self): print(f"{self.nome} ataca você!")Você precisa criar um zumbi com 100 de vida. Qual das opções cria corretamente esse objeto?
Alternativas:
- (A)
inimigo = Inimigo("Zumbi", 100) - (B)
inimigo = Inimigo(nome="Zumbi") - (C)
zumbi = nome.Inimigo("Zumbi", 100) - (D)
inimigo = new Inimigo("Zumbi", 100)
Exercício 1.3: O Molde e a Peça (Conceito)
Seção intitulada “Exercício 1.3: O Molde e a Peça (Conceito)”Competência: Distinguir classe de objeto e aplicar a analogia do molde.
Pergunta:
Explique, com suas palavras, a diferença entre classe e objeto usando a analogia do molde de kart. Depois, dê um exemplo da engenharia da computação (fora dos jogos) em que a mesma ideia de “molde e peça produzida” se aplica.
Nível 2: Construtor
Seção intitulada “Nível 2: Construtor”O estúdio precisa que você escreva construtores capazes de inicializar os atributos de cada novo objeto. O __init__ é o seu instrumento.
Exercício 2.1: Criando Personagens (Programação)
Seção intitulada “Exercício 2.1: Criando Personagens (Programação)”Competência: Escrita de construtores com __init__ e criação de objetos com atributos iniciais.
Contexto:
O RPG do estúdio está em pré-produção. Todo herói precisa nascer com nome, vida e mana. Você é responsável por finalizar o esqueleto da classe Personagem, escrevendo o construtor que recebe esses três valores e os guarda como atributos.
Instruções:
- Defina a classe
Personageme implemente o construtor que armazena os valores recebidos nos atributosnome,vidaemana. - Crie os personagens
Aric(vida100, mana50) eLuna(vida80, mana100). - Imprima as informações de cada personagem no formato abaixo.
Saída esperada:
Aric tem 100 de vida e 50 de mana.Luna tem 80 de vida e 100 de mana.Exercício 2.2: Montando a Playlist (Múltipla escolha)
Seção intitulada “Exercício 2.2: Montando a Playlist (Múltipla escolha)”Competência: Reconhecer o construtor compatível com uma chamada de criação.
Contexto:
O módulo de trilha sonora do estúdio instancia uma playlist assim:
playlist = Playlist("Rock", 15)Qual das opções implementa corretamente a classe Playlist para que essa chamada funcione como esperado (gênero "Rock", quantidade 15)?
Alternativas:
- (A)
class Playlist: def __init__(self, genero, quantidade): self.genero = genero self.quantidade = quantidade- (B)
class Playlist: def __init__(self): self.genero = "Rock" self.quantidade = 15- (C)
class Playlist: def __init__(genero, quantidade): self.genero = genero self.quantidade = quantidade- (D)
class Playlist: def __init__(self, quantidade, genero): self.genero = genero self.quantidade = quantidadeExercício 2.3: O Nascimento do Objeto (Conceito)
Seção intitulada “Exercício 2.3: O Nascimento do Objeto (Conceito)”Competência: Compreender o papel e o momento de execução do construtor.
Pergunta:
Explique o que é o método __init__ e em que momento exato ele é executado. O que acontece com os atributos de um objeto se uma classe não definir esse método? Justifique por que é importante que a inicialização dos atributos aconteça no construtor em vez de ficar solta no código.
Nível 3: Métodos com self
Seção intitulada “Nível 3: Métodos com self”Agora você vai dar comportamento aos objetos. Nesta missão, self é a chave para cada objeto manipular seus próprios dados.
Exercício 3.1: O Combate (Programação)
Seção intitulada “Exercício 3.1: O Combate (Programação)”Competência: Criação de métodos que usam self para ler e alterar atributos do próprio objeto.
Contexto:
O FPS da Byte está com o combate quase pronto. A classe Jogador já tem o construtor definido. Seu trabalho é implementar os três métodos de combate que manipulam os atributos de cada jogador de forma individual.
Classe fornecida:
class Jogador: def __init__(self, nome, vida, dano): self.nome = nome self.vida = vida self.dano = danoInstruções:
- Implemente o método
receber_dano(quantidade), que reduz avidado próprio jogador. - Implemente o método
atacar(inimigo), que reduz a vida do inimigo usando o próprio dano do atacante e imprime a mensagem{nome} causou {dano} de dano em {nome_do_inimigo}!. - Implemente o método
curar(quantidade), que aumenta avidado próprio jogador e imprime{nome} recuperou {quantidade} de vida!. - No programa principal, execute exatamente a sequência abaixo:
player = Jogador("Rafa", 100, 25)chefe = Jogador("Hydra", 200, 40)
player.atacar(chefe)chefe.atacar(player)player.curar(15)print(player.vida)print(chefe.vida)Saída esperada:
Rafa causou 25 de dano em Hydra!Hydra causou 40 de dano em Rafa!Rafa recuperou 15 de vida!75175Exercício 3.2: Dois Contadores (Múltipla escolha)
Seção intitulada “Exercício 3.2: Dois Contadores (Múltipla escolha)”Competência: Prever o comportamento de um método utilizando self em objetos diferentes.
Contexto:
O estúdio usa essa classe para contar eventos no jogo:
class Contador: def __init__(self, valor): self.valor = valor
def incrementar(self): self.valor += 1
contador_a = Contador(5)contador_b = Contador(10)
contador_a.incrementar()contador_b.incrementar()contador_b.incrementar()
print(contador_a.valor, contador_b.valor)Qual será a saída impressa?
Alternativas:
- (A)
6 12 - (B)
8 12 - (C)
6 11 - (D)
5 10
Exercício 3.3: Quem é o self? (Conceito)
Seção intitulada “Exercício 3.3: Quem é o self? (Conceito)”Competência: Explicar o papel de self em métodos de instância.
Pergunta:
O que é self em um método de classe? Por que ele aparece como primeiro parâmetro de todo método de instância? Descreva o erro que ocorre quando você chama um método esquecendo o self na definição, e explique por que self é essencial quando dois objetos da mesma classe precisam se relacionar (como um herói atacando outro).
Nível 4: Encapsulamento
Seção intitulada “Nível 4: Encapsulamento”A Byte ganhou um módulo financeiro. Dinheiro não pode ser alterado por qualquer um, seus dados precisam de proteção. Bem-vindo ao encapsulamento.
Exercício 4.1: CarteiraDigital (Programação)
Seção intitulada “Exercício 4.1: CarteiraDigital (Programação)”Competência: Atributos privados, getters e setters com validação.
Contexto:
O jogo vai ter moeda digital própria. Você precisa blindar a classe CarteiraDigital para que ninguém mexa no saldo diretamente. A classe já possui os atributos __titular e __saldo no construtor, mas todas as portas de acesso ainda precisam ser construídas.
Classe fornecida:
class CarteiraDigital: def __init__(self, titular, saldo_inicial): self.__titular = titular self.__saldo = saldo_inicialInstruções:
- Crie o getter
get_titular(), que retorna o nome do titular. - Crie o getter
get_saldo(), que retorna o saldo atual. - Crie o setter
set_saldo(valor), que recusa valores negativos: sevalorfor menor que zero, imprimaErro: saldo não pode ser negativo.sem alterar o saldo; caso contrário, atualize o saldo. - No programa principal, execute exatamente a sequência abaixo:
carteira = CarteiraDigital("Ana", 100.0)
print(f"Saldo de {carteira.get_titular()}: R$ {carteira.get_saldo()}")carteira.set_saldo(carteira.get_saldo() + 250.0)print(f"Saldo de {carteira.get_titular()}: R$ {carteira.get_saldo()}")carteira.set_saldo(-50.0)print(f"Saldo de {carteira.get_titular()}: R$ {carteira.get_saldo()}")Saída esperada:
Saldo de Ana: R$ 100.0Saldo de Ana: R$ 350.0Erro: saldo não pode ser negativo.Saldo de Ana: R$ 350.0Exercício 4.2: Proibido Tocar (Múltipla escolha)
Seção intitulada “Exercício 4.2: Proibido Tocar (Múltipla escolha)”Competência: Identificar o acesso correto e o acesso bloqueado a atributos privados.
Contexto:
O estúdio rastreia o carrinho de compras dos jogadores com esta classe:
class Carrinho: def __init__(self): self.__itens = 0
def get_itens(self): return self.__itens
carrinho = Carrinho()Qual das linhas abaixo, executada logo após a criação do carrinho, gera um erro AttributeError?
Alternativas:
- (A)
print(carrinho.get_itens()) - (B)
print(carrinho.__itens) - (C)
print(carrinho.get_itens() + 1) - (D)
print(carrinho.get_itens)
Exercício 4.3: O Cofre do Objeto (Conceito)
Seção intitulada “Exercício 4.3: O Cofre do Objeto (Conceito)”Competência: Explicar o encapsulamento e o roteiro para aplicá-lo.
Pergunta:
Explique o que é encapsulamento e os três passos do roteiro para aplicá-lo em uma classe (atributos privados, getters e setters). Por que não basta apenas tornar os atributos privados, por que os setters, em especial, são úteis quando o dado precisa de regras (como um saldo que não pode ser negativo)? Dê um exemplo de um problema que pode acontecer se todos os atributos de um sistema forem públicos.
Nível 5: Desafio, O Duelo de Heróis
Seção intitulada “Nível 5: Desafio, O Duelo de Heróis”Missão final: o MOBA da Byte está em beta e você vai montar o coração do combate. Este desafio integra tudo que você aprendeu: criação de classe, construtor, self, encapsulamento e a interação entre objetos.
Exercício 5.1: Construindo o Heroi (Programação)
Seção intitulada “Exercício 5.1: Construindo o Heroi (Programação)”Competência: Projetar uma classe completa integrando construtor, métodos com self e encapsulamento com getters/setters.
Contexto:
Cada partida do MOBA é um duelo entre dois heróis. Você deve implementar a classe Heroi do zero, com todos os atributos blindados, e simular um duelo entre dois heróis até um deles ser derrotado.
Instruções:
- Crie a classe
Heroicom o construtor com os atributosnome,vidaeataque. - Torne os atributos privados.
- Crie getters e setters para os três atributos. Os setters de
vidaeataquedevem ajustar valores fora do intervalo, limitandovidaentre0e100eataqueentre0e99. - Implemente o método
atacar(oponente), que reduz a vida do oponente de acordo com oataquedo herói (use os getters/setters do oponente) e imprime{nome} ataca {nome_do_oponente} ({nome_do_oponente}: {vida_atual}). - Implemente o método
esta_vivo(), que retornaTruese a vida for maior que0. - No programa principal, declare o vencedor da partida com o laço abaixo:
alfa = Heroi("Alfa", 100, 35)beta = Heroi("Beta", 90, 20)
while alfa.esta_vivo() and beta.esta_vivo(): alfa.atacar(beta) if beta.esta_vivo(): beta.atacar(alfa)
if alfa.esta_vivo(): print("Alfa venceu o duelo!")else: print("Beta venceu o duelo!")Saída esperada:
Alfa ataca Beta (Beta: 55)Beta ataca Alfa (Alfa: 80)Alfa ataca Beta (Beta: 20)Beta ataca Alfa (Alfa: 60)Alfa ataca Beta (Beta: 0)Alfa venceu o duelo!Exercício 5.2: Lendo o Duelo (Múltipla escolha)
Seção intitulada “Exercício 5.2: Lendo o Duelo (Múltipla escolha)”Competência: Interpretar o estado dos objetos após métodos que usam self e getters/setters.
Contexto:
Em outra partida de teste, o código a seguir foi executado com a classe Heroi do exercício anterior:
x = Heroi("X", 80, 30)y = Heroi("Y", 70, 25)
x.atacar(y)y.atacar(x)x.atacar(y)Qual é o estado correto dos heróis ao final (vida de x e vida de y)?
Alternativas:
- (A) x: 55, y: 10
- (B) x: 50, y: 20
- (C) x: 55, y: 30
- (D) x: 50, y: 10
Exercício 5.3: Avaliando o Design (Conceito)
Seção intitulada “Exercício 5.3: Avaliando o Design (Conceito)”Competência: Avaliar decisões de projeto em orientação a objetos.
Pergunta:
Sobre a solução do duelo de heróis, responda com argumentos:
- Por que o atributo
__vidade um herói deve ser privado e alterado apenas por métodos comoatacare pelos setters? - O método
atacar(oponente)poderia ser uma função solta do tipoatacar(alfa, beta)do lado de fora da classe? Compare as duas formas em termos de organização e reutilização de código. - O que
selfrepresenta dentro do métodoatacarquando o duelo é executado? Explique o que acontece quando o programa criaalfaebeta, mostrando que cada objeto mantém seu próprio__vidae__ataque.