Introdução
A Programação Orientada a Objetos (POO) organiza o código em torno de objetos, que representam entidades com dados e comportamentos. Nesta página, vamos revisar os conceitos fundamentais de POO usando JavaScript, preparando a base para o desenvolvimento web que veremos ao longo da disciplina.
Configuração do ambiente para os exemplos
Você pode executar os exemplos desta unidade diretamente no navegador (recomendado para começar) ou com Node.js.
Opção 1 – Navegador
- Crie uma pasta em seu computador, por exemplo
prog2-revisao-oo. -
Dentro da pasta, crie um arquivo chamado
index.htmlcom o conteúdo abaixo.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<title>Revisão OO - Programação II</title>
</head>
<body>
<h1>Revisão de Orientação a Objetos em JavaScript</h1>
<p>Abra o console do navegador para ver a saída dos exemplos.</p>
<script src="revisao-oo.js"></script>
</body>
</html>
-
Crie um arquivo chamado
revisao-oo.jsna mesma pasta. É nele que você vai colar os exemplos de código desta página. -
Abra o arquivo
index.htmlno navegador (clique duas vezes ou use “Abrir com > Navegador”). - Pressione F12 e selecione a aba Console para ver a saída dos códigos.
Entendendo o arquivo HTML base
O bloco abaixo é uma explicação “anotada” do arquivo HTML anterior. Leia junto com o exemplo para entender o papel de cada linha.
<!DOCTYPE html>- Indica ao navegador que o documento usa HTML5, permitindo uma renderização mais padronizada.
<html lang="pt-BR">- Abre a tag raiz do documento HTML e informa que o idioma principal da página é português do Brasil, o que ajuda na acessibilidade e em mecanismos de busca.
<head> ... </head>- Define a área de metadados da página, onde ficam informações que não aparecem diretamente na tela (configuração de caracteres, título, links de estilo etc.).
<meta charset="UTF-8" />- Configura a codificação de caracteres para UTF‑8, garantindo que acentos e demais caracteres especiais sejam exibidos corretamente.
<title>Revisão OO - Programação II</title>- Define o texto que aparece na aba do navegador e é usado por favoritos e motores de busca como o título da página.
<body> ... </body>- Delimita o corpo do documento, isto é, todo o conteúdo visível para quem acessa a página (textos, imagens, botões, scripts em execução etc.).
<h1>Revisão de Orientação a Objetos em JavaScript</h1>- Cria o título principal da página. Por padrão é exibido em destaque e marca o assunto mais importante do documento.
-
<p>Abra o console do navegador para ver a saída dos exemplos.</p> - Exibe um parágrafo com instruções para o usuário, orientando que ele abra o console do navegador para acompanhar a saída do código JavaScript.
<script src="revisao-oo.js"></script>-
Importa e executa o arquivo externo
revisao-oo.js. Todo o JavaScript escrito nesse arquivo é carregado quando a página abre e sua saída aparece no console. </html>- Fecha o documento HTML, indicando ao navegador que não há mais conteúdo a ser processado.
Opção 2 – Node.js (para quem já instalou)
- Instale o Node.js a partir do site oficial, se ainda não tiver.
-
Na mesma pasta, mantenha o arquivo
revisao-oo.jscom os exemplos. -
Abra um terminal na pasta e execute:
node revisao-oo.js
Objetivos da unidade
- Explicar o que é programação orientada a objetos e como ela é usada em sistemas web.
- Definir e utilizar classes e objetos em JavaScript, seguindo boas práticas de código.
- Aplicar os pilares de POO: abstração, encapsulamento, herança e polimorfismo.
- Implementar pequenos modelos de domínio (como Estudante, ContaBancaria, Produto) que poderão servir de base para o projeto da disciplina.
1. Conceitos básicos de POO em JavaScript
1.1 Classe e objeto
Em POO, a classe é um molde que descreve quais dados e comportamentos um tipo de objeto terá, enquanto o objeto é uma instância concreta dessa classe.
// Exemplo 1 – Classe Produto
class Produto {
constructor(nome, preco) {
if (!nome || typeof nome !== 'string') {
throw new Error('Nome do produto deve ser uma string não vazia.');
}
if (typeof preco !== 'number' || preco <= 0) {
throw new Error('Preço deve ser um número positivo.');
}
this.nome = nome;
this.preco = preco;
}
aplicarDesconto(percentual) {
if (typeof percentual !== 'number' || percentual <= 0 || percentual >= 100) {
throw new Error('Percentual deve ser um número entre 0 e 100.');
}
const fatorDesconto = 1 - percentual / 100;
this.preco *= fatorDesconto;
}
descrever() {
const precoFormatado = this.preco.toFixed(2);
return `${this.nome} - R$ ${precoFormatado}`;
}
}
// Uso da classe Produto
const mouse = new Produto('Mouse sem fio', 80);
const teclado = new Produto('Teclado mecânico', 350);
mouse.aplicarDesconto(10);
console.log('Produtos cadastrados:');
console.log(mouse.descrever());
console.log(teclado.descrever());
Entendendo o Exemplo 1 – Classe Produto
Este exemplo mostra como modelar um produto usando uma classe em JavaScript, incluindo validação de dados e um método para aplicar desconto.
class Produto { ... }-
Define uma nova classe chamada
Produto, que servirá como “molde” para criar objetos que representam produtos à venda. constructor(nome, preco) { ... }-
O construtor é chamado quando criamos um novo produto. Ele recebe o
nomee oprecocomo parâmetros, valida esses dados (não aceita nome vazio nem preço menor ou igual a zero) e, se estiver tudo certo, guarda esses valores dentro do objeto. aplicarDesconto(percentual) { ... }-
Este método recebe um percentual de desconto e também faz validação
(entre 0 e 100). Em seguida, calcula um fator de desconto e atualiza o atributo
precomultiplicando pelo fator. Assim, o próprio objeto “sabe” como aplicar descontos sobre si mesmo. descrever() { ... }- Gera uma string amigável com o nome do produto e o preço formatado com duas casas decimais. Essa é uma forma de centralizar a formatação em um único lugar, facilitando o reuso em diferentes partes do sistema.
const mouse = new Produto(...)/const teclado = new Produto(...)-
Aqui criamos dois objetos concretos (instâncias) da classe
Produto: um mouse e um teclado, cada um com seu próprio preço. mouse.aplicarDesconto(10);-
Chamamos o método da instância
mousepara aplicar um desconto de 10%. Apenas o preço do mouse é atualizado; o teclado continua com o valor original. console.log(...)-
As chamadas ao
console.logservem para exibir no console o texto “Produtos cadastrados” e, em seguida, a descrição de cada produto retornada pelo métododescrever(). É assim que verificamos, na prática, se o código está se comportando como esperado.
1.2 Atributos, métodos e responsabilidade
Uma boa prática é manter cada classe com uma responsabilidade clara.
No exemplo abaixo, a classe Estudante é responsável por representar o estado
acadêmico de um estudante em um curso.
// Exemplo 2 – Classe Estudante
class Estudante {
constructor(nome, matricula, curso) {
if (!nome || !matricula || !curso) {
throw new Error('Estudante precisa de nome, matrícula e curso.');
}
this.nome = nome;
this.matricula = matricula;
this.curso = curso;
this.status = 'Em andamento';
}
aprovar() {
this.status = 'Aprovado';
}
reprovar() {
this.status = 'Reprovado';
}
obterResumo() {
return `${this.nome} (${this.matricula}) - ${this.curso} - ${this.status}`;
}
}
const maria = new Estudante('Maria', '2026001', 'Engenharia de computação');
console.log(maria.obterResumo());
maria.aprovar();
console.log(maria.obterResumo());
2. Pilares da Programação Orientada a Objetos
2.1 Abstração
Abstrair significa representar apenas o que é relevante de um objeto para o contexto do sistema, ignorando detalhes desnecessários.
// Exemplo 3 – Classe Professor
class Professor {
constructor(nome, cpf, area) {
if (!nome || !cpf || !area) {
throw new Error('Professor precisa de nome, CPF e área.');
}
this.nome = nome;
this.cpf = cpf;
this.area = area;
}
resumo() {
return `${this.nome} (${this.area})`;
}
}
const profWilcilene = new Professor('Wilcilene Maria Kowal', '123.456.789-00', 'Programação II, que não é Web');
console.log(profWilcilene.resumo());
2.2 Encapsulamento
Encapsulamento significa proteger os dados de acesso direto indevido,
expondo apenas o que realmente precisa ser público. Em JavaScript podemos usar
campos privados com #.
// Exemplo 4 – ContaBancaria com atributo privado
class ContaBancaria {
#saldo;
constructor(titular) {
if (!titular) {
throw new Error('Conta precisa de um titular.');
}
this.titular = titular;
this.#saldo = 0;
}
depositar(valor) {
if (typeof valor !== 'number' || valor <= 0) {
throw new Error('Depósito deve ser um número positivo.');
}
this.#saldo += valor;
}
sacar(valor) {
if (typeof valor !== 'number' || valor <= 0) {
throw new Error('Saque deve ser um número positivo.');
}
if (valor > this.#saldo) {
throw new Error('Saldo insuficiente para saque.');
}
this.#saldo -= valor;
}
obterSaldo() {
return this.#saldo;
}
}
const contaGilsilene = new ContaBancaria('Gilsilene');
contaGilsilene.depositar(500);
contaGilsilene.sacar(150);
console.log(`Saldo da conta de ${contaGilsilene.titular}: R$ ${contaGilsilene.obterSaldo()}`);
// contaGilsilene.#saldo = 9999; // Erro: campo privado
2.3 Herança
Herança permite reaproveitar código criando classes mais específicas a partir de uma
mais geral. Usamos extends e super() em JavaScript.
// Exemplo 5 – Usuário e Admin
class Usuario {
constructor(nome, email) {
if (!nome || !email) {
throw new Error('Usuário precisa de nome e email.');
}
this.nome = nome;
this.email = email;
}
apresentar() {
console.log(`Olá, eu sou ${this.nome}.`);
}
}
class Admin extends Usuario {
constructor(nome, email) {
super(nome, email);
this.perfil = 'ADMIN';
}
bloquearUsuario(usuario) {
if (!(usuario instanceof Usuario)) {
throw new Error('É possível bloquear apenas um objeto do tipo Usuario.');
}
console.log(`Usuário ${usuario.nome} foi bloqueado por ${this.nome}.`);
}
}
const usuarioJoao = new Usuario('João', 'joao@exemplo.com');
const adminMaria = new Admin('Maria', 'maria@exemplo.com');
usuarioJoao.apresentar();
adminMaria.apresentar();
adminMaria.bloquearUsuario(usuarioJoao);
2.4 Polimorfismo
Polimorfismo é a capacidade de um mesmo método ter comportamentos diferentes, dependendo da classe concreta do objeto.
// Exemplo 6 – Formas geométricas
class Forma {
calcularArea() {
throw new Error('Método calcularArea() deve ser implementado pela subclasse.');
}
}
class Retangulo extends Forma {
constructor(largura, altura) {
super();
if (largura <= 0 || altura <= 0) {
throw new Error('Largura e altura devem ser positivas.');
}
this.largura = largura;
this.altura = altura;
}
calcularArea() {
return this.largura * this.altura;
}
}
class Circulo extends Forma {
constructor(raio) {
super();
if (raio <= 0) {
throw new Error('Raio deve ser positivo.');
}
this.raio = raio;
}
calcularArea() {
return Math.PI * this.raio ** 2;
}
}
function imprimirArea(forma) {
if (!(forma instanceof Forma)) {
throw new Error('O parâmetro deve ser uma instância de Forma.');
}
console.log('Área:', forma.calcularArea().toFixed(2));
}
imprimirArea(new Retangulo(3, 4));
imprimirArea(new Circulo(2));
Áudio criado pelo NotebokLM após análise desta página
Use o player abaixo para ouvir a explicação gravada deste tema
3. Para memorizar!
Atividade 1 – Modelando uma turma
Modele as classes abaixo em JavaScript, seguindo as práticas estudadas nos exemplos (validação de dados, nomes claros, responsabilidade única).
Curso: possui nome e carga horária.-
Turma: está ligada a um curso e contém uma lista de estudantes (Estudante).
Regras sugeridas:
- Não permitir estudantes duplicados na turma (mesma matrícula).
- Garantir que toda turma esteja ligada a um curso válido.
Atividade 2 – Encapsulando um carrinho de compras
Implemente uma classe CarrinhoDeCompras com:
- Lista interna de itens (cada item com
descricao,preco,quantidade). - Métodos:
adicionarItem,removerItem,calcularTotal,listarItens.
Regras:
- Não aceitar quantidade zero ou negativa.
- Esconder a lista interna (encapsulamento) e expor apenas métodos de acesso.
Atividade 3 – Herança e polimorfismo com veículos
Implemente:
Veiculocommarca,modelo,anoe métododescricao().CarroeMoto, que herdam deVeiculoe sobrescrevemdescricao().
Crie uma função imprimirDescricao(veiculo) que recebe qualquer
Veiculo (ou subclasse) e chama descricao(),
demonstrando polimorfismo.
Atividade 4 – Biblioteca
Crie as classes Livro, UsuarioBiblioteca e,
se achar necessário, uma classe para controlar empréstimos.
Regras sugeridas:
- Use encapsulamento para proteger a lista interna de livros emprestados.
- Impeça que o mesmo livro seja emprestado duas vezes para o mesmo usuário.
- Inclua um método para listar todos os empréstimos ativos.
Atividade 5 – Sistema de pagamentos
Crie uma hierarquia de Pagamento com subclasses para
PagamentoCartao, PagamentoPix e
PagamentoBoleto.
Orientações:
-
Defina na classe base um método
processar()que é sobrescrito em cada subclasse com a lógica específica de mensagem ou validação. -
Implemente uma função
pagar(pagamento)que recebe qualquer objeto da hierarquia e chamaprocessar(), explorando o polimorfismo.
Roteiro de estudo para quem faltou
Assista à explicação dessa aula gerada pelo NotebookLM.
- Configure o ambiente (seção “Configuração do ambiente para os exemplos”).
-
Reproduza todos os exemplos de código em seu arquivo
revisao-oo.js, alterando valores e observando o resultado. - Resolva os exercícios propostos.
- Anote dúvidas pontuais para discutirmos na próxima aula.