Ao final dessa aula você vai saber como escrever um programa em Python utilizando funções e classes. .. , e importar classes usando import. No futuro...
- Exercício com programação orientada a objetos;
- Classe com um objeto como atributo;
- Uso de módulos e import.
Para problemas simples, as vantagens do uso de Programação Orientada à Objetos (POO) talvez não fiquem tão claras. Para sistemas complexos, com vários componentes, suas vantagens ficam mais evidentes. Portanto vamos tentar evidenciar essas vantagens com problemas um pouco mais complexos.
Uma vantagem da orientação à objetos é que ela nos permite pensar de forma mais concreta e próxima do comportamento real de componentes de um sistema (ao contrário, por exemplo, de um modelo puramente abstrato).
Uma forma de tratar um problema utilizando objetos é por meio da definição do comportamento dos objetos, antes de implementá-los. Modelar objetos não é uma tarefa simples e, na prática, podem existir vários modelamentos possíveis, cada um com suas vantagens e desvantagens.
Uma forma possível de modelamento é dividir o problema em componentes na forma que você achar mais “natural” (e podem haver várias formas “naturais”!), definindo como cada componente deve se comportar e interagir com os demais componentes, e então criar classes para representar cada componente.
Vamos resolver um exercício mais complexo para ilustrar esse processo.
Vamos pensar por exemplo em como poderíamos resolver o exercício programa Encha de água usando objetos.
Basicamente, o jogo é uma simulação, onde o usuário deve encher um balde com o máximo volume possível de água. A capacidade do balde no entanto é inicialmente desconhecida, e pode variar entre 10 e 50 unidades.
A cada jogada, o jogo sorteia uma quantidade de água, mostra essa quantidade ao usuário e pergunta se o usuário deseja ou não utilizá-la. o jogo (simulação) termina quando o balde estiver cheio ou o usuário desistir de colocar mais água no balde. Para facilitar, o jogo avisa quando o volume armazenado chega ou ultrapassa a metade da capacidade do balde.
Parte A - Modelamento inicial
O programa abaixo descreve, em Python, esse comportamento.
O objetivo dessa primeira parte foi “modelar” o simulador e definir as ações desse objeto. Se essa classe existisse, o nosso programa estaria pronto. Nos parece também que a classe Simulador vai precisar trabalhar com objetos do tipo Balde.
Para chegar nesse programa inicial, como o jogo precisa sortear quantidades de água de forma pseudo-aleatória, “delegamos” as funções para gerenciar esses sorteios a classe Simulador e imaginamos então que a classe precisa receber uma semente ao ser construída. Os demais métodos, deposita() e finaliza(), correspondem às demais ações de um jogo.
Parte B
O próximo passo seria definir a classe Simulador, mas como ela depende de uma outra classe, a Balde, que nos parece mais simples de definir, vamos começar pela definição de Balde.
Para ser utilizado em um jogo, um objeto balde deve precisar dos atributos:
- capacidade : int que indica capacidade máxima do balde
- volume : int volume atual de água no balde
- derramado : água derramada
- cheio : booleano indica se o balde está cheio
Observação
O processo de definição de classes e seus atributos e método é iterativo. Uma vez definido alguns atributos e métodos básicos, a definição de uma classe deve evoluir a medida que as demais classes são definidas. Um outro aspecto que pode ser explorado é criar classes que sejam genéricas, para que possam ser utilizadas em outros problemas. Vamos tentar reutilizar a classe Balde no próximo exercício, e apenas estender a classe Simulador.
Ao criar um Balde, é necessário definir o valor do atributo capacidade, e podemos zerar os atributos volume e derramado.
Ao imprimir um Balde, por exemplo contendo 12 unidades de volume, ele deve corresponder ao texto *12* caso esteja cheio e [12] caso ainda possua volume livre.
A classe deve ter o método deposita(self, v), que recebe uma quantidade de água vol e atualiza o estado do objeto Balde.
Parte C
Vamos definir agora a classe Simulador. A idea de se criar essa classe é agrupar o estado e operações específicas do simulador (jogo). Vamos incluir também no Simulador todas as operação com random e, para isso, o construtor dessa classe deve receber a semente para o gerador de números pseudo-aleatórios. O construtor deve também inicializar os seguintes atributos:
- balde : objeto Balde
- vol : volume sorteado
- avisou : indica se uma mensagem avisando se o balde atingiu ou passou da metade já foi dada.
Os demais métodos da classe são:
sorteia(self): que sorteia um volume de água de 1 a 10 unidades atualizando o atributo vol, e imprime esse volume.
deposita(self): que adiciona o volume vol ao balde. Observe que a função main usa o método deposita do Simulador, mas esse volume deve ser passado do Simulador ao Balde, simplificando as ações necessárias na main.
O método deposita retorna True se o balde ficar cheio após a operação, e imprime uma mensagem da primeira vez que o volume atingir ou passar da metade da capacidade.
finaliza(self): imprime as seguintes mensagens:
- Fim da simulação
- Capacidade do balde: ___
- Volume final: ___
- Balde está (ou não) cheio
- Volume derramado:
Parte D
Junte as partes anteriores para ter o programa completo. O programa principal (função main) controla a entrada e a saída (usando input e print) com o usuário e o Simulador mantém o estado da simulação e controla o “jogo”.
Usando a mesma classe Balde do Exercício 19.1, modifique a função main e a classe Simulador para implementar o exercício programa Encha de água mais ainda.