Conceitos de POO em Java
Visão geral da programação orientada a objetos em Java: encapsulamento, herança, polimorfismo e abstração.
Programação orientada a objetos (POO) é uma forma de organizar o código em torno das coisas do seu programa, e não dos passos. Em vez de um longo script que opera sobre variáveis brutas, você descreve os tipos de objetos do seu domínio — um User, um Order, um BankAccount — e dá a cada um os dados e o comportamento de que precisa. O restante do programa então pede que esses objetos façam coisas, em vez de mexer diretamente em seus internos.
Java foi construído em torno dessa ideia. Cada linha de código Java que você escreve vive dentro de uma classe, e uma classe é o molde a partir do qual objetos são criados. Até este ponto, você tem escrito código majoritariamente procedural dentro de main e alguns auxiliares estáticos; a partir desta parte do livro, você começa a projetar suas próprias classes.
Classes e objetos em uma frase
Uma classe descreve um tipo de coisa — quais dados ela armazena e o que ela pode fazer. Um objeto é uma instância específica dessa coisa.
public class Dog {
String name;
int age;
void bark() {
System.out.println(name + " says woof");
}
}
Dog d = new Dog(); // d is an object — one specific dog
d.name = "Rex";
d.bark(); // Rex says woofDog é a classe. d é um objeto. A grande mudança em relação ao código procedural: um objeto agrupa estado (os campos name e age) e comportamento (o método bark()) em uma única unidade. Você pode criar quantos objetos Dog quiser; cada um recebe sua própria cópia de name e age, e cada um pode executar bark() de forma independente. O capítulo de classes e objetos explora isso em detalhes.
Os quatro pilares
A POO é geralmente ensinada em torno de quatro ideias. Cada uma recebe um capítulo completo mais adiante nesta parte do livro — o que se segue é um tour rápido para que você saiba para onde o caminho leva.
Encapsulamento
Mantenha os dados de um objeto privados; exponha o comportamento em vez disso. O código externo chama account.deposit(50), não account.balance += 50. O benefício é que a classe controla seus próprios invariantes — ninguém mais pode colocá-la em um estado inválido.
public class Account {
private int balance; // hidden
public void deposit(int amount) { // public behavior
if (amount <= 0) throw new IllegalArgumentException();
balance += amount;
}
}Veja o capítulo de encapsulamento.
Herança
Uma classe pode estender outra, herdando seus campos e métodos e adicionando a eles. Cat extends Animal reutiliza tudo que Animal já faz e especifica apenas o que é diferente nos gatos.
public class Animal {
void breathe() { System.out.println("inhale, exhale"); }
}
public class Cat extends Animal {
void purr() { System.out.println("rrr"); }
}
Cat c = new Cat();
c.breathe(); // inherited
c.purr(); // ownVeja o capítulo de herança.
Polimorfismo
A mesma chamada pode fazer coisas diferentes dependendo do objeto real que está na outra ponta. Uma variável do tipo Animal pode apontar para um Cat, um Dog ou um Cow — chamar speak() nela seleciona o comportamento correto em tempo de execução.
Animal a = new Cat();
a.speak(); // calls Cat's speak, even though a is typed as AnimalVeja o capítulo de polimorfismo.
Abstração
Defina o que algo faz sem se comprometer com como. Uma interface Shape diz que toda forma tem um método area(); cada forma concreta — Circle, Square — fornece sua própria fórmula. O código que trabalha com formas não precisa saber qual tipo é.
public interface Shape {
double area();
}Veja o capítulo de abstração.
Os pilares em resumo
| Pilar | Ideia em uma linha | Ferramenta Java |
|---|---|---|
| Encapsulamento | Ocultar dados, expor comportamento | Campos private + métodos públicos |
| Herança | Reutilizar e estender outra classe | extends |
| Polimorfismo | Uma chamada, comportamento escolhido em tempo de execução | sobrescrita + variáveis de supertipo |
| Abstração | Definir o que, não como | interfaces e classes abstratas |
Os pilares se sobrepõem propositalmente: o polimorfismo depende da herança, a abstração é reforçada pelo encapsulamento, e assim por diante. Trate-os como quatro ângulos de uma única ideia — modele seu programa como objetos que cooperam — em vez de quatro recursos separados para memorizar.
Por que se preocupar?
Para um script de 20 linhas, a POO é exagero. O ganho aparece à medida que os programas crescem:
- Raciocínio local. Uma classe
BankAccountpossui suas próprias regras. Para entender ou alterar depósitos, você lê o métododeposit— não precisa fazer grep no código em busca debalance +=. - Reutilização sem copiar e colar. Herança e composição permitem que
SavingsAccountseja construída sobreAccountem vez de duplicá-la. - Substituibilidade. Uma função que recebe um
Shapefunciona para toda forma que existe hoje e para qualquer uma que você adicionar amanhã. - Testabilidade. Objetos pequenos com responsabilidades claras são fáceis de instanciar, acionar e verificar com assertivas.
Java está longe de ser a única linguagem orientada a objetos — Python, C#, Kotlin, Ruby e muitas outras compartilham as mesmas ideias com sintaxe diferente. O que você aprende nesta parte é transferível.
A POO não é o único paradigma
Mesmo dentro do Java, você já escreveu código que não é estritamente OO: métodos utilitários estáticos, matemática primitiva, fluxo de controle simples. O Java moderno mistura paradigmas — pipelines funcionais com streams e lambdas, dados imutáveis com records, trabalho declarativo com anotações. A POO é a espinha dorsal da linguagem, não uma gaiola. Use uma classe quando estiver modelando algo com estado e comportamento; recorra a um método estático quando precisar apenas de um cálculo.
Um exemplo trabalhado
O código completo dos trechos acima, reunido para que você possa executá-lo:
O que vem a seguir
Agora que você conhece o formato da POO, o próximo capítulo fixa seus fundamentos: como uma definição de classe se torna um objeto na memória, o que new realmente faz e como referências de objetos diferem de primitivos. Continue em classes e objetos em Java.