(Voltar ao menu anterior)
Curso: Tecnologia em Sistemas para Internet • 2º semestre

Introdução à Orientação a Objetos (ARQINOO)

Aula 03: Paradigma Orientado a Objetos

Conceitos de Encapsulamento, Herança e Classes Abstratas • Java + VS Code


Prof. José Rodolfo Beluzo

Logo

Objetivos da Aula

  • Compreender a estrutura de pacotes packages e suas funcionalidades.
  • Revisar encapsulamento (proteção de dados e camada de acesso pública).
  • Compreender herança (reuso e especialização).
  • Compreender classes abstratas (contratos parciais).
  • Compreender interfaces
  • Aplicar em exercícios práticos com Java + VS Code.

Pacotes (Packages)

Pacotes organizam classes e evitam conflitos de nomes.

  • Convenção: br.ifsp.arqinoo.projeto
  • Mapeiam a estrutura de pastas do projeto
  • Controlam visibilidade com o modificador package-private (sem palavra‑chave)
// src/br/ifsp/arqinoo/model/Produto.java
package br.ifsp.arqinoo.model;

public class Produto {
  private final String nome;
  public Produto(String n){ this.nome = n; }
  public String getNome(){ return nome; }
}

// src/br/ifsp/arqinoo/app/Main.java
package br.ifsp.arqinoo.app;
import br.ifsp.arqinoo.model.Produto;

public class Main {
  public static void main(String[] args){
    Produto p = new Produto("Café");
    System.out.println(p.getNome());
  }
}

Em VS Code, use Java: Create Java Project e crie pacotes com clique direito → New Package.

Organização sugerida

src/
  br/ifsp/arqinoo/app/        → classes de inicialização (Main)
  br/ifsp/arqinoo/model/      → entidades de domínio (POJOs)
  br/ifsp/arqinoo/service/    → regras de negócio
  br/ifsp/arqinoo/util/       → utilitários

Separe responsabilidades: facilita testes e manutenção.

Encapsulamento

Esconder o estado interno e expor operações seguras.

  • private em campos
  • getters/setters com validação
  • imutabilidade quando possível
public class ContaBancaria {
  private double saldo;

  public void depositar(double v){
    if (v > 0) saldo += v;
  }
  public boolean sacar(double v){
    if (v > 0 && v <= saldo){
      saldo -= v; return true;
    }
    return false;
  }
  public double getSaldo(){ return saldo; }
}

Por que saldo não é público? Como garantir invariantes?

Herança

Permite reuso e especialização. Use com parcimônia.

  • extends indica relação “é-um”.
  • super() chama construtor da base.
  • Prefira composição quando não houver hierarquia clara.
public class Funcionario {
  protected String nome;
  protected double salario;
  public Funcionario(String n,double s){
    nome=n; salario=s;
  }
  public double getSalario(){return salario;}
}

public class Gerente extends Funcionario {
  private double bonus;
  public Gerente(String n,double s,double b){
    super(n,s); bonus=b;
  }
  public double salarioTotal(){
    return salario + bonus;
  }
}

Use protected com cuidado: mantém encapsulamento parcial.

Modificadores de Acesso e Controle

Controlam a visibilidade e o comportamento de classes, atributos e métodos.

🔒 Níveis de Acesso

  • public — visível por todas as classes.
  • protected — visível na mesma classe, pacote e subclasses.
  • (sem modificador) — visível apenas dentro do mesmo pacote (package-private).
  • private — visível apenas dentro da própria classe.

⚙️ Modificadores de Comportamento

  • final — impede alterações:
    • final class → não pode ser herdada
    • final method → não pode ser sobrescrito
    • final variable → valor constante
  • static — pertence à classe, e não ao objeto.
  • abstract — indica classe ou método incompleto (precisa ser implementado).

// Exemplo prático
public class Conta {
    private double saldo;      // acesso restrito
    protected String titular;  // visível por subclasses
    public final String banco = "IFSP Bank"; // constante

    public double getSaldo() { // acesso público controlado
        return saldo;
    }
}
  

➤ Bons projetos usam os modificadores para garantir encapsulamento e segurança no código.

Classes Abstratas

  • Não podem ser instanciadas.
  • Definem contratos parciais: métodos abstratos.
  • Podem ter estado e métodos concretos.
public abstract class Animal {
  protected String nome;
  public Animal(String n){ nome = n; }
  public abstract void emitirSom();
}

public class Cachorro extends Animal {
  public Cachorro(String n){ super(n); }
  @Override public void emitirSom(){
    System.out.println(nome+" faz: Au Au!");
  }
}

Quando usar: há um conceito geral, mas a implementação varia por tipo.

Comparativo Rápido

ConceitoPara quê?Palavras-chave
EncapsulamentoProteger estado / API mínimaprivate, getters/setters
HerançaReuso por especializaçãoextends, super()
Classe AbstrataModelo com lacunasabstract, @Override

Exercício 1 — Encapsulamento

  1. Implemente Produto com campos privados nome e preco.
  2. Valide no setPreco que o valor >= 0.
  3. Torne a classe imutável (opcional) removendo setters.
public class Produto {
  private final String nome;
  private final double preco;
  public Produto(String n,double p){
    if(n==null || n.isBlank()) throw new IllegalArgumentException("nome");
    if(p < 0) throw new IllegalArgumentException("preco");
    nome=n; preco=p;
  }
  public String getNome(){return nome;}
  public double getPreco(){return preco;}
}

Exercício 2 — Herança

Modele PessoaAluno e Professor. Adicione comportamento específico.

class Pessoa {
  protected String nome; protected int idade;
  public Pessoa(String n,int i){ nome=n; idade=i; }
}
class Aluno extends Pessoa {
  private String curso;
  public Aluno(String n,int i,String c){ super(n,i); curso=c; }
}
class Professor extends Pessoa {
  private double salario;
  public Professor(String n,int i,double s){ super(n,i); salario=s; }
}

Exercício 3 — Classe Abstrata

Crie Forma com calcularArea(). Implemente Circulo e Retangulo.

abstract class Forma { abstract double calcularArea(); }
class Circulo extends Forma {
  private final double r; public Circulo(double r){this.r=r;}
  double calcularArea(){ return Math.PI*r*r; }
}
class Retangulo extends Forma {
  private final double w,h; public Retangulo(double w,double h){this.w=w;this.h=h;}
  double calcularArea(){ return w*h; }
}

Exercício 4 — Integração

Implemente Funcionario (abstrata) com calcularSalarioFinal() e subclasses:

  • Gerente: salário base + bônus
  • Vendedor: Salário base + comissão de venda
  • Estagiario: bolsa fixa

O salário base deve ser pertencente à classe Funcionario utilizando "static".
A bolsa fixa é só do estagiário.
O bônus é fixo, estipulado para cada gerente.
A comissão é em porcentagem (10%) do valor vendido.

public abstract class Funcionario {
  protected String nome; protected double base;
  public Funcionario(String n,double b){ nome=n;base=b; }
  public abstract double calcularSalarioFinal();
}
class Vendedor extends Funcionario {
  private double comissao; public Vendedor(String n,double b,double c){super(n,b);comissao=c;}
  public double calcularSalarioFinal(){ return base + comissao; }
}

Interfaces

  • Definem contratos (métodos sem estado)
  • Permitem herança múltipla de tipos (uma classe pode implementar várias interfaces)
  • Podem ter default e static methods
public interface Calculavel {
  double calcular();
  default boolean valido(){ return calcular() >= 0; }
}

public class Pedido implements Calculavel {
  private double total;
  public Pedido(double t){ this.total = t; }
  @Override public double calcular(){ return total; }
}

Use interfaces para comportamentos compartilháveis entre classes sem forçar hierarquia.

Múltiplas interfaces

Uma classe pode implementar várias interfaces:

public interface Exportavel { String exportar(); }
public interface Identificavel { String getId(); }

public class Relatorio implements Exportavel, Identificavel {
  private final String id;
  public Relatorio(String id){ this.id = id; }
  public String exportar(){ return "# Relatório " + id; }
  public String getId(){ return id; }
}
  • Promove composição de comportamentos
  • Evita árvores profundas de herança
  • Facilita testes (mocks via interfaces)

Interface × Classe Abstrata

InterfaceClasse Abstrata
Estado (campos)Não (apenas consts)Sim
HerançaMúltiplas implementaçõesUma superclasse
Uso típicoContrato de comportamentoModelo com implementação parcial
Métodos concretosdefault/staticSim, comuns à hierarquia

Regra prática: comece com interface; migre para abstrata se precisar de estado/implementação compartilhada.

Exercício — Interfaces

  1. Crie a interface Notificavel com enviarNotificacao().
  2. Implemente em Pedido (envia resumo) e Estoque (avisa falta).
  3. Adicione um método default logEnvio() na interface.
public interface Notificavel {
  void enviarNotificacao(String destino);
  default void logEnvio(String destino){
    System.out.println("Enviado para: " + destino);
  }
}

Teste polimorfismo: crie List<Notificavel> e itere chamando enviarNotificacao.

Checklist de Aprendizagem

  • Encapsulamento protege o estado e define API mínima.
  • Herança para especializar (use com critério; considere composição).
  • Classes abstratas definem contratos parciais.

Próximos passos: Interfaces, Polimorfismo, e Testes Unitários.