Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@ Proporcionar aos estudantes uma experiência prática e progressiva dos conceito
### Fundamentos de POO

#### Classes e Objetos

- **Classe**: Um modelo ou template que define a estrutura e comportamento de objetos. É como um "molde" que especifica quais atributos (dados) e métodos (funções) os objetos terão.
- **Objeto**: Uma instância específica de uma classe. É a materialização concreta do modelo definido pela classe.
- **Instanciação**: O processo de criar um objeto a partir de uma classe usando o operador de chamada `()`.

#### Construtores

- **Método `__init__()`**: Método especial chamado automaticamente quando um objeto é criado. Responsável por inicializar os atributos do objeto.
- **Parâmetros do Construtor**: Valores passados durante a criação do objeto para configurar seu estado inicial.
- **Self**: Referência ao próprio objeto, usado para acessar atributos e métodos da instância.

#### Atributos e Métodos

- **Atributos de Instância**: Variáveis que pertencem a cada objeto específico, definidas com `self.atributo`.
- **Atributos de Classe**: Variáveis compartilhadas por todas as instâncias da classe.
- **Métodos de Instância**: Funções que operam sobre dados específicos de cada objeto.
Expand All @@ -30,17 +33,21 @@ Proporcionar aos estudantes uma experiência prática e progressiva dos conceito
### Encapsulamento

#### Princípio do Encapsulamento

O encapsulamento é um dos pilares fundamentais da POO que consiste em:

- **Ocultar detalhes internos**: Proteger dados e implementação interna da classe
- **Controlar acesso**: Definir como os dados podem ser acessados e modificados
- **Manter integridade**: Garantir que o objeto sempre esteja em um estado válido

#### Níveis de Visibilidade em Python

- **Público**: Atributos e métodos acessíveis de qualquer lugar (`atributo`)
- **Protegido**: Convenção para indicar uso interno, prefixo `_` (`_atributo`)
- **Privado**: Dificultam acesso externo, prefixo `__` (`__atributo`)

#### Properties e Getters/Setters

- **@property**: Decorator que permite acessar métodos como se fossem atributos
- **Getter**: Método para obter o valor de um atributo privado
- **Setter**: Método para definir o valor de um atributo com validação
Expand All @@ -49,11 +56,13 @@ O encapsulamento é um dos pilares fundamentais da POO que consiste em:
### Herança

#### Conceitos Fundamentais

- **Classe Base (Pai/Superclasse)**: Classe que define características comuns
- **Classe Derivada (Filha/Subclasse)**: Classe que herda e especializa a classe base
- **Relação "é um"**: A herança representa uma relação hierárquica onde a subclasse "é um" tipo da superclasse

#### Mecanismos de Herança

- **Herança Simples**: Uma classe herda de apenas uma classe pai
- **Herança Múltipla**: Uma classe herda de múltiplas classes pai (suportada em Python)
- **Método super()**: Função que permite chamar métodos da classe pai
Expand All @@ -63,41 +72,48 @@ O encapsulamento é um dos pilares fundamentais da POO que consiste em:
### Polimorfismo

#### Definição e Tipos

- **Polimorfismo**: Capacidade de objetos de diferentes classes responderem à mesma interface de forma específica
- **Polimorfismo de Sobrescrita**: Mesmo método implementado diferentemente em classes relacionadas por herança
- **Polimorfismo de Interface**: Objetos não relacionados que implementam os mesmos métodos

#### Benefícios do Polimorfismo

- **Flexibilidade**: Código que funciona com diferentes tipos de objetos
- **Extensibilidade**: Facilita adição de novos tipos sem modificar código existente
- **Manutenibilidade**: Reduz acoplamento entre componentes do sistema

### Relacionamentos entre Objetos

#### Composição

- **Definição**: Relacionamento "tem um" onde um objeto contém outros objetos como partes integrantes
- **Ciclo de Vida**: Os objetos componentes dependem do objeto principal
- **Exemplo**: Um Carro "tem um" Motor - se o carro é destruído, o motor também é

#### Agregação

- **Definição**: Relacionamento "usa um" onde objetos existem independentemente mas se referenciam
- **Ciclo de Vida**: Os objetos podem existir separadamente
- **Exemplo**: Um Professor "leciona para" Alunos - professor e alunos existem independentemente

#### Relacionamentos N:N (Muitos para Muitos)

- **Definição**: Múltiplos objetos de um tipo se relacionam com múltiplos objetos de outro tipo
- **Implementação**: Geralmente usando listas ou conjuntos para armazenar referências
- **Exemplo**: Alunos podem estar matriculados em várias Disciplinas, e cada Disciplina pode ter vários Alunos

### Recursos Avançados

#### Métodos de Classe (@classmethod)

- **Propósito**: Métodos que operam sobre a classe, não sobre instâncias específicas
- **Primeiro Parâmetro**: `cls` (referência à classe)
- **Uso Comum**: Factory methods (métodos fábrica) para criar objetos de formas específicas
- **Acesso**: Podem ser chamados tanto pela classe quanto por instâncias

#### Métodos Estáticos (@staticmethod)

- **Propósito**: Funções relacionadas à classe mas que não precisam acessar dados da classe ou instância
- **Parâmetros**: Não recebem `self` nem `cls` automaticamente
- **Uso Comum**: Funções utilitárias relacionadas ao domínio da classe
Expand Down Expand Up @@ -205,12 +221,14 @@ Todos os exercícios são baseados em entidades e situações de uma **escola de
Antes de submeter sua solução, você pode executar os testes localmente para verificar se sua implementação está correta:

#### Pré-requisitos

```bash
# Instale as dependências
pip install -r requirements.txt
```

#### Executando um teste específico

```bash
# Para testar apenas o exercício 1
python -m pytest tests/test_exercicio01.py -v
Expand All @@ -220,24 +238,28 @@ python -m pytest tests/test_exercicio02.py -v
```

#### Executando todos os testes

```bash
# Executa todos os testes do projeto
python -m pytest tests/ -v
```

#### Interpretando a saída dos testes

- **PASSED**: Teste passou - sua implementação está correta
- **FAILED**: Teste falhou - verifique a mensagem de erro
- **ERROR**: Erro de importação - verifique o nome do arquivo

#### Exemplo de saída de teste bem-sucedido

```
tests/test_exercicio01.py::test_aluno_creation PASSED
tests/test_exercicio01.py::test_disciplina_creation PASSED
tests/test_exercicio01.py::test_aluno_attributes PASSED
```

#### Exemplo de saída com erro

```
tests/test_exercicio01.py::test_aluno_creation FAILED
E AttributeError: 'Aluno' object has no attribute 'nome'
Expand Down Expand Up @@ -374,4 +396,4 @@ Para dúvidas sobre os exercícios:

---

**Bons estudos!**
**Bons estudos!**
96 changes: 96 additions & 0 deletions Resposta_10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Relatório: Erros encontrados e correções - Exercício 10

Abaixo estão os 7 erros identificados no código fornecido, a solução aplicada e o princípio de POO envolvido.

---

**Erro 1**: Nome da classe em minúsculas

- Descrição: A classe foi declarada como `class pessoa:` (nome em minúsculas). Pela convenção do Python e boas práticas de POO, nomes de classes devem usar PascalCase.
- Solução: Renomeada para `class Pessoa:`.
- Conceito POO: Convenção de nomenclatura / legibilidade.

---

**Erro 2**: Atributo `nome` não atribuído ao objeto

- Descrição: No construtor foi usado `nome = nome` (atribuição local), em vez de `self.nome = nome`. Isso não cria o atributo de instância.
- Solução: Corrigido para `self.nome = nome` no `__init__` de `Pessoa`.
- Conceito POO: Encapsulamento / inicialização de atributos de instância.

---

**Erro 3**: Uso incorreto / falta de inicialização do atributo `__cpf`

- Descrição: Existia uma referência solta a `self.__cpf` no construtor (ou em algumas versões faltava a atribuição). Esse uso sem atribuição provoca `AttributeError` ou é ambíguo.
- Solução: Inicializar o atributo privado corretamente: `self.__cpf = None`.
- Conceito POO: Encapsulamento / atributos privados (name mangling). Inicialização correta de estado do objeto.

---

**Erro 4**: Método `apresentar` sem parâmetro `self`

- Descrição: O método foi definido como `def apresentar():`, sem o parâmetro `self`, tornando impossível acessar `self.nome` dentro do método.
- Solução: Alterado para `def apresentar(self):` e uso de `self.nome` para compor a string.
- Conceito POO: Métodos de instância devem aceitar `self` como primeiro parâmetro.

---

**Erro 5**: Inicialização incorreta na subclasse `Estudante`

- Descrição: A classe `Estudante` atribuía manualmente `self.nome = nome` e `self.idade = idade` invés de reutilizar o construtor da superclasse, perdendo lógica de inicialização e manutenção.
- Solução: Usar `super().__init__(nome, idade)` dentro de `Estudante.__init__` para reaproveitar a inicialização da classe `Pessoa`.
- Conceito POO: Herança e reutilização de construtores com `super()`.

---

**Erro 6**: Cálculo de média sem tratamento de casos especiais

- Descrição: O cálculo `sum(self.notas) / len(self.notas)` assume que `self.notas` não está vazia; quando lista vazia, causa `ZeroDivisionError`.
- Solução parcial/relacionada: implementar verificação antes da divisão (feito na solução final abaixo).
- Conceito POO / Lógica: Validação de estado do objeto e tratamento de exceções.

---

**Erro 7**: Chamada de `calcular_media` com lista de notas vazia

- Descrição: O teste no final do script chama `estudante.calcular_media()` sem ter adicionado nenhuma nota, resultando em `ZeroDivisionError` no código original.
- Solução: Implementar proteção dentro de `calcular_media` para retornar `0.0` quando `self.notas` estiver vazia. Assim, a chamada é segura e o programa não levanta exceção inesperada. A implementação atual em `Resposta_10.py` é:

```python
def calcular_media(self):
# Evita divisão por zero quando não há notas registradas
if not self.notas:
return 0.0
return sum(self.notas) / len(self.notas)
```

- Conceito POO / Lógica: Validação de estado do objeto; tratamento de entradas inválidas / ausência de dados.

---

## Observações sobre outras escolhas de design

- O atributo `__cpf` foi mantido como privado (com double-underscore). Isso aplica name-mangling no Python e é adequado se a intenção for tornar o acesso direto mais difícil. Alternativamente, pode-se usar um único underscore (`_cpf`) ou implementar getters/setters para controlar acesso.
- Ao retornar `0.0` para `calcular_media` quando não há notas, optamos por um comportamento seguro e previsível. Outra alternativa seria lançar uma exceção explícita (`ValueError`) para forçar o chamador a validar a existência de notas antes de pedir a média. A escolha depende do comportamento esperado pela aplicação.

---

## Resultado do teste

Rodando o script `Resposta_10.py` após as correções, a saída é similar a:

```
Olá, sou João
Olá, sou o professor Dr. Silva do departamento Computação
Média do estudante: 0.0
```

Isso indica que o programa não produz exceções ao calcular a média quando não há notas (resultado `0.0`).

---

Arquivos entregues:

- `Resposta_10.py` (corrigido)
- `Resposta_10.md` (este relatório)
43 changes: 43 additions & 0 deletions Resposta_10.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
class Pessoa:
def __init__(self, nome, idade):
self.nome = nome
self.idade = idade

def apresentar(self):
return f"Olá, sou {self.nome}"

class Estudante(Pessoa):
def __init__(self, nome, idade, curso):
super().__init__(nome, idade)
self.curso = curso
self.notas = []

def adicionar_nota(self, nota):
if nota >= 0 and nota <= 10:
self.notas.append(nota)

def calcular_media(self):
# Evita divisão por zero quando não há notas registradas
if not self.notas:
return 0.0
return sum(self.notas) / len(self.notas)
class Professor(Pessoa):
def __init__(self, nome, idade, departamento, salario):
super().__init__(nome, idade)
self.departamento = departamento
self.salario = salario

def apresentar(self):
return f"Olá, sou o professor {self.nome} do departamento {self.departamento}"

# Testando o código
estudante = Estudante("João", 20, "Engenharia")
professor = Professor("Dr. Silva", 45, "Computação", 8000)

print(estudante.apresentar())
print(professor.apresentar())

estudante.adicionar_nota(8)
estudante.adicionar_nota(7)

print(f"Média do estudante: {estudante.calcular_media()}") # Erro 7
8 changes: 6 additions & 2 deletions exercicio_01.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Exercício 01 - Modelagem Básica de Entidades

## Objetivo

Praticar a criação de classes simples e inicialização de objetos.

## Descrição do Exercício

Crie duas classes: **Aluno** e **Disciplina**.

### Requisitos:
### Requisitos

1. **Classe Aluno** deve ter atributos para:
- nome
Expand All @@ -23,12 +25,14 @@ Crie duas classes: **Aluno** e **Disciplina**.
4. Instancie dois objetos de cada classe e imprima seus atributos.

## Entrega

Crie um arquivo chamado `respExercicio01.py` com a implementação das classes e a criação dos objetos solicitados.

## Exemplo de Saída Esperada

```
Aluno: João Silva, Matrícula: 2023001, Curso: Engenharia de Software
Aluno: Maria Santos, Matrícula: 2023002, Curso: Ciência da Computação
Disciplina: Programação Orientada a Objetos, Código: POO001, Carga Horária: 60h
Disciplina: Banco de Dados, Código: BD001, Carga Horária: 80h
```
```
9 changes: 7 additions & 2 deletions exercicio_05.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Exercício 05 - Herança e o Uso de super()

## Objetivo

Entender e utilizar a função super() no construtor da classe filha.

## Descrição do Exercício

Aprimore a classe **Funcionario** do exercício 4 utilizando corretamente a função `super()`.

### Requisitos:
### Requisitos

1. No construtor (`__init__`) de **Funcionario**, utilize `super().__init__(...)` para inicializar os atributos herdados de **Pessoa**.

Expand All @@ -17,20 +19,23 @@ Aprimore a classe **Funcionario** do exercício 4 utilizando corretamente a fun
4. Crie um objeto Funcionario e garanta que todos os atributos (herdados e próprios) foram inicializados corretamente.

## Entrega

Crie um arquivo chamado `respExercicio05.py` com a implementação aprimorada usando `super()`.

## Exemplo de Uso

```python
funcionario = Funcionario("Ana Costa", "111.222.333-44", "20/03/1988", "Coordenadora", 4500.0)
funcionario.exibir_dados()
```

## Exemplo de Saída Esperada

```
=== Dados do Funcionário ===
Nome: Ana Costa
CPF: 111.222.333-44
Data de Nascimento: 20/03/1988
Cargo: Coordenadora
Salário: R$ 4500.0
```
```
Loading