Polimorfismo e Abstração
Polimorfismo é uma característica central da OOP que torna o código mais flexível e extensível.
O que é Polimorfismo
Polimorfismo significa que o mesmo método se comporta de maneira diferente em objetos diferentes.
Benefícios do Polimorfismo
| Benefício | Descrição |
|---|---|
| Flexibilidade | Mesma interface, diferentes implementações |
| Extensibilidade | Adicionar novas subclasses não requer modificar o código pai |
| Código simplificado | Usar referências da classe pai para operar em objetos filhos |
Upcasting
Um objeto filho pode ser atribuído a uma referência da classe pai.
Animal animal = new Dog(); // Upcasting
Exemplo: Upcasting
public class Animal {
public void eat() {
System.out.println("Animal está comendo");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("Cão está roendo um osso");
}
public void bark() {
System.out.println("Latindo");
}
}
public class PolymorphismDemo {
public static void main(String[] args) {
Animal animal = new Dog(); // Upcasting
animal.eat(); // Cão está roendo um osso (chama o eat do Dog)
// animal.bark(); // Erro de compilação! Referência pai só pode acessar métodos pai
}
}
Vinculação Dinâmica
Em tempo de execução, o método é chamado com base no tipo real do objeto, não no tipo em tempo de compilação.
Exemplo: Vinculação Dinâmica
public class Animal {
public void speak() {
System.out.println("Animal faz um som");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Au au");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Miau miau");
}
}
public class DynamicBinding {
public static void makeSound(Animal animal) {
animal.speak(); // Decidido em tempo de execução qual speak chamar
}
public static void main(String[] args) {
makeSound(new Dog()); // Au au
makeSound(new Cat()); // Miau miau
}
}
Classes Abstratas
Classes abstratas não podem ser instanciadas—só podem ser herdadas.
Métodos Abstratos
Métodos sem corpo que as subclasses devem implementar.
public abstract class Shape {
// Método abstrato: sem corpo
public abstract double area();
// Método regular: tem corpo
public void display() {
System.out.println("Área: " + area());
}
}
Exemplo: Classe Abstrata
public abstract class Shape {
protected String name;
public Shape(String name) {
this.name = name;
}
// Métodos abstratos
public abstract double area();
public abstract double perimeter();
public void display() {
System.out.println(name + " - Área: " + area() + ", Perímetro: " + perimeter());
}
}
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
super("Círculo");
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
}
public class Rectangle extends Shape {
private double width, height;
public Rectangle(double width, double height) {
super("Retângulo");
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
@Override
public double perimeter() {
return 2 * (width + height);
}
}
public class ShapeDemo {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rect = new Rectangle(4, 6);
circle.display(); // Círculo - Área: 78.54, Perímetro: 31.42
rect.display(); // Retângulo - Área: 24.0, Perímetro: 20.0
}
}
Interfaces
Interfaces definem um conjunto de regras que as classes de implementação devem seguir.
Definição de Interface
public interface NomeDaInterface {
// Constantes (padrão public static final)
int MAX_SIZE = 100;
// Métodos abstratos (padrão public abstract)
void method1();
int method2(int a);
}
Implementação de Interface
public class NomeDaClasse implements NomeDaInterface {
@Override
public void method1() {
// Implementação
}
@Override
public int method2(int a) {
return a;
}
}
Exemplo: Interface
public interface Flyable {
void fly();
}
public interface Swimmable {
void swim();
}
public class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("Pato está voando");
}
@Override
public void swim() {
System.out.println("Pato está nadando");
}
}
public class InterfaceDemo {
public static void main(String[] args) {
Duck duck = new Duck();
duck.fly(); // Pato está voando
duck.swim(); // Pato está nadando
// Referência de interface
Flyable flyer = new Duck();
flyer.fly();
}
}
Interface vs Classe Abstrata
| Característica | Interface | Classe Abstrata |
|---|---|---|
| Palavra-chave | interface |
abstract class |
| Implementação | implements |
extends |
| Múltipla implementação | Suportado | Não suportado |
| Construtores | Nenhum | Tem construtores |
| Variáveis de membro | Apenas constantes | Pode ter variáveis regulares |
| Métodos | Métodos abstratos (pré-Java 8) | Pode ter métodos regulares |
Programação Orientada a Interface
public interface Payment {
void pay(double amount);
}
public class Alipay implements Payment {
@Override
public void pay(double amount) {
System.out.println("Pagamento Alipay: $" + amount);
}
}
public class WechatPay implements Payment {
@Override
public void pay(double amount) {
System.out.println("Pagamento WeChat: $" + amount);
}
}
public class PaymentDemo {
// Programar para interface
public static void checkout(Payment payment, double amount) {
payment.pay(amount);
}
public static void main(String[] args) {
checkout(new Alipay(), 100); // Pagamento Alipay: $100.0
checkout(new WechatPay(), 200); // Pagamento WeChat: $200.0
}
}
❓ Perguntas Frequentes
P: Quando devo usar classe abstrata vs interface? R: Use classes abstratas quando tiver estado e comportamento compartilhados. Use interfaces quando precisar apenas definir um contrato.
P: Interfaces podem ter corpos de métodos? R: Sim, desde o Java 8, você pode usar a palavra-chave
defaultpara definir métodos padrão.
P: Posso chamar métodos específicos do filho após upcasting? R: Não, você precisa fazer downcast (cast explícito) primeiro.
📖 Resumo
- Polimorfismo: o mesmo método se comporta de maneira diferente em objetos diferentes
- Upcasting: atribuir um objeto filho a uma referência pai
- Vinculação dinâmica: método chamado com base no tipo real do objeto em tempo de execução
- Classes abstratas não podem ser instanciadas; podem ter métodos abstratos e regulares
- Interfaces definem contratos que as classes de implementação devem seguir
📝 Exercícios
- Hierarquia de animais: Defina uma classe abstrata Animal com subclasses Dog e Cat, implemente chamadas polimórficas
- Cálculos de formas: Defina uma interface Shape, implemente Circle e Rectangle, calcule áreas
- Sistema de pagamento: Defina uma interface Payment, implemente múltiplos métodos de pagamento
Próxima Lição
Na próxima lição, aprenderemos sobre Interfaces Avançadas e Lambda — características de interfaces e expressões Lambda.



