Conceitos de Encapsulamento, Herança e Classes Abstratas • Java + VS Code
Prof. José Rodolfo Beluzo
Pacotes organizam classes e evitam conflitos de nomes.
br.ifsp.arqinoo.projetopackage-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.
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.
Esconder o estado interno e expor operações seguras.
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?
Permite reuso e especialização. Use com parcimônia.
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.
Controlam a visibilidade e o comportamento de classes, atributos e métodos.
final class → não pode ser herdadafinal method → não pode ser sobrescritofinal variable → valor constante
// 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.
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.
| Conceito | Para quê? | Palavras-chave |
|---|---|---|
| Encapsulamento | Proteger estado / API mínima | private, getters/setters |
| Herança | Reuso por especialização | extends, super() |
| Classe Abstrata | Modelo com lacunas | abstract, @Override |
Produto com campos privados nome e preco.setPreco que o valor >= 0.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;}
}
Modele Pessoa → Aluno 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; }
}
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; }
}
Implemente Funcionario (abstrata) com calcularSalarioFinal() e subclasses:
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; }
}
default e static methodspublic 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.
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; }
}
| Interface | Classe Abstrata | |
|---|---|---|
| Estado (campos) | Não (apenas consts) | Sim |
| Herança | Múltiplas implementações | Uma superclasse |
| Uso típico | Contrato de comportamento | Modelo com implementação parcial |
| Métodos concretos | default/static | Sim, comuns à hierarquia |
Regra prática: comece com interface; migre para abstrata se precisar de estado/implementação compartilhada.
Notificavel com enviarNotificacao().Pedido (envia resumo) e Estoque (avisa falta).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.
Próximos passos: Interfaces, Polimorfismo, e Testes Unitários.