POO Java - Orientação a Objetos Java
POO Java - Orientação a Objetos Java
Fala, Dev! Usei o poder da inteligência artificial, para criar um conteúdo diferenciado com o foco em te apresentar todos os
tópicos de orientação a objetos usando Java, que acredito que você vai precisar em um futuro próximo. Esse conteúdo é para
ser compartilhado com todos que desejam aprender programação orientada a objetos. Tornando o aprendizado colaborativo.
Leia os conteúdos, crie os códigos, adapte-os, teste, use-o para estudar para provas, testes, concursos, e principalmente, para
fazer da programação Java a sua profissão, e se tornar um programador(a), um Dev melhor.
Não tenha medo de usar inteligência artificial para tirar as dúvidas que surgirem aqui, e potencializar ainda mais o seus
estudos. O meu canal do youtube acima tem vários projetos, conceitos e práticas que você pode desenvolver e fortalecer tudo
na prática.
Aproveite e Conheça todos os meus cursos e acelere ainda mais o seu aprendizado:
• Java na Prática – Do Básico ao Avançado: https://pay.kiwify.com.br/55BuhNc
• Projeto Java Full Stack, Sistema de Lanchonete: https://pay.kiwify.com.br/V8tIuJ3
• Projeto Java Back-end, Sistema de Gestão de Atendimentos: https://pay.kiwify.com.br/0vmjNYG
• Java na Web com Spring Boot: https://pay.kiwify.com.br/meoh7va
• Java no Front-end para Desktop: https://pay.kiwify.com.br/TxhrQlt
• Java no Front-end para Web com Spring Boot: https://pay.kiwify.com.br/QcDb7zc
Sucesso!
Sumário:
1. Fundamentos da Orientação a Objetos
• Objetos e Classes
• Atributos e Métodos
• Mensagens e Comunicação entre Objetos
• Abstração
• Encapsulamento
• Herança
• Polimorfismo
3. Modificadores de Acesso
• private
• protected
• public
• package-private (sem modificador)
Classe
É um modelo ou molde para criar objetos. Define os atributos (dados) e métodos (comportamentos) de um objeto.
Objeto
É uma instância de uma classe, criada a partir de seu modelo. Ele contém valores próprios para seus atributos e pode executar
métodos definidos na classe.
Exemplo em Java
// Definição de uma classe
class Carro {
String marca;
int ano;
void buzinar() {
System.out.println("Biiiii!");
}
}
Resumo: Uma classe define o que um objeto pode ter e fazer. Um objeto é uma cópia dessa classe em memória.
1.2 Abstração
A abstração permite representar um objeto do mundo real destacando somente os aspectos essenciais e ignorando detalhes
irrelevantes.
Exemplo
Imagine um carro. Para um programador, ele precisa saber apenas alguns atributos e comportamentos, como:
Atributos → cor, modelo, ano, marca.
Métodos → acelerar(), frear(), ligar().
Detalhes como o funcionamento interno do motor não são relevantes para a abstração do carro.
Exemplo em Java
abstract class Veiculo {
String modelo;
int ano;
Resumo: A abstração foca nos atributos e métodos essenciais de um objeto, ignorando detalhes internos.
1.3 Encapsulamento
O encapsulamento protege os dados do objeto, impedindo que sejam modificados diretamente. Ele é implementado usando
modificadores de acesso (private, public, protected).
Benefícios do Encapsulamento
Protege os dados do objeto.
Evita acessos e modificações indevidas.
Facilita a manutenção do código.
Vantagens da Herança
Reutiliza código.
Facilita a manutenção.
Evita redundância.
void dormir() {
System.out.println("Dormindo...");
}
}
Resumo: A herança permite que uma classe herde atributos e métodos de outra classe.
1.5 Polimorfismo
O polimorfismo permite que um mesmo método tenha diferentes comportamentos, dependendo do contexto.
Tipos de Polimorfismo
• Polimorfismo de Sobrescrita (Override)
• Polimorfismo de Sobrecarga (Overload)
Resumo: O polimorfismo permite que métodos se comportem de maneiras diferentes dependendo do contexto.
Conclusão
Esses são os quatro fundamentos da POO:
Abstração → Esconder detalhes desnecessários.
Encapsulamento → Proteger os dados do objeto.
Herança → Reutilizar código de outra classe.
Polimorfismo → Permitir comportamentos diferentes para um mesmo método.
Quer aprofundar algum conceito?
2. Princípios da POO (SOLID)
O SOLID é um conjunto de cinco princípios definidos por Robert C. Martin (Uncle Bob), que ajudam a criar código mais
organizado, flexível e de fácil manutenção.
Esses princípios são essenciais para desenvolver sistemas modulares, reutilizáveis e que seguem boas práticas de design.
S – Single Responsibility Principle (Princípio da Responsabilidade Única)
O – Open/Closed Principle (Princípio Aberto/Fechado)
L – Liskov Substitution Principle (Princípio da Substituição de Liskov)
I – Interface Segregation Principle (Princípio da Segregação de Interfaces)
D – Dependency Inversion Principle (Princípio da Inversão de Dependência)
Agora, vamos explorar cada um deles em detalhes com exemplos práticos em Java.
void salvarEmArquivo() {
System.out.println("Salvando relatório no disco...");
}
}
class RelatorioArquivo {
void salvarEmArquivo(Relatorio relatorio) {
System.out.println("Salvando relatório no disco...");
}
}
Problema: Sempre que um novo tipo de cliente surgir, precisamos modificar essa classe.
Aplicando OCP (Correto)
interface Desconto {
double calcular(double valor);
}
class CalculadoraDesconto {
double aplicarDesconto(Desconto desconto, double valor) {
return desconto.calcular(valor);
}
}
Agora, se quisermos adicionar um novo tipo de cliente (exemplo: "SuperVIP"), basta criar uma nova classe sem
modificar o código existente!
2.3 L – Liskov Substitution Principle (LSP)
Subtipos devem ser substituíveis por seus tipos base sem quebrar o sistema.
Isso significa que se uma classe herda de outra, ela deve manter o comportamento esperado, sem alterar funcionalidades
essenciais.
int getArea() {
return largura * altura;
}
}
@Override
void setAltura(int altura) {
this.largura = altura;
this.altura = altura; // FORÇANDO a largura = altura
}
}
Problema: O Quadrado altera o comportamento de Retangulo, violando o LSP.
Problema: A classe Desenvolvedor é obrigada a implementar um método que não faz sentido para ela.
interface Atendente {
void realizarAtendimento();
}
Agora, cada classe implementa apenas as interfaces que fazem sentido para ela!
2.5 D – Dependency Inversion Principle (DIP)
Dependa de abstrações, não de implementações concretas.
Exemplo de Violação do DIP (Errado)
class MySQLDatabase {
void conectar() { System.out.println("Conectando ao MySQL..."); }
}
class Aplicacao {
private MySQLDatabase database = new MySQLDatabase();
}
class Aplicacao {
private Database database;
Conclusão
Os princípios SOLID garantem código mais organizado, escalável e fácil de manter.
Quer aprofundar algum deles?
3. Padrões de Projetos (Design Patterns)
Os Design Patterns são soluções reutilizáveis para problemas comuns no desenvolvimento de software. Eles foram
catalogados pelo Gang of Four (GoF) no livro Design Patterns: Elements of Reusable Object-Oriented Software.
3.1.1 Singleton
Garante que uma classe tenha apenas uma única instância e fornece um ponto global de acesso a ela.
Exemplo de Singleton em Java
class Configuracao {
private static Configuracao instancia;
class Fabrica {
static Produto criarProduto(String tipo) {
if (tipo.equals("A")) return new ProdutoA();
if (tipo.equals("B")) return new ProdutoB();
return null;
}
}
O cliente chama Fabrica.criarProduto("A"), sem saber qual classe concreta será usada.
3.2 Padrões Estruturais (Structural Patterns)
Os padrões estruturais organizam a composição entre classes e objetos.
3.2.1 Adapter
Permite que classes incompatíveis trabalhem juntas.
Exemplo de Adapter
class TomadaAntiga {
void conectar() { System.out.println("Conectado à tomada antiga!"); }
}
interface NovaTomada {
void conectarNovo();
}
Agora um sistema novo pode usar a TomadaAntiga sem precisar modificar seu código!
3.2.2 Composite
Permite tratar um grupo de objetos da mesma maneira que um único objeto.
Exemplo de Composite
interface Componente {
void mostrar();
}
3.3.1 Strategy
Permite escolher algoritmos em tempo de execução.
Exemplo de Strategy
interface EstrategiaPagamento {
void pagar(double valor);
}
class Checkout {
private EstrategiaPagamento estrategia;
Exemplo de Observer
interface Observador {
void atualizar(String mensagem);
}
class Notificador {
private List<Observador> observadores = new ArrayList<>();
Conclusão
Os Design Patterns ajudam a construir sistemas modulares, flexíveis e reutilizáveis. Eles resolvem problemas comuns e
tornam o código mais organizado.
Se quiser aprofundar em algum padrão específico, me avise!
4. UML (Unified Modeling Language)
A UML (Linguagem de Modelagem Unificada) é um padrão para modelar sistemas orientados a objetos.
Ela fornece diagramas visuais que ajudam a projetar, visualizar e documentar a estrutura e o comportamento de um sistema.
Explicação:
• Pessoa tem os atributos nome e idade.
• Estudante herda (extends) Pessoa e adiciona matricula.
Exemplo UML
+----------------+
| pessoa1:Pessoa |
+----------------+
| nome = "Ana" |
| idade = 25 |
+----------------+
Exemplo UML
+-------------------+
| Servidor Web |
| Apache Tomcat |
+-------------------+
|
▼
+-------------------+
| Banco de Dados |
| MySQL |
+-------------------+
Exemplo UML
+--------------------------------+
| Sistema de Login |
+--------------------------------+
▲
|
+----------------+ +----------------+
| Usuário | | Admin |
+----------------+ +----------------+
| |
| |
+--------+ +-------------+
| Logar | | Gerenciar |
+--------+ | Usuários |
+-------------+
Mostra que o "Usuário" pode fazer login, e o "Admin" pode gerenciar usuários.
Conclusão
A UML ajuda a planejar, visualizar e documentar sistemas antes mesmo de escrever código.
Se quiser aprofundar em algum diagrama, me avise!
5. Princípios SOLID
Os princípios SOLID são um conjunto de boas práticas de design de software para tornar o código mais modular, flexível e
fácil de manter.
Se precisarmos mudar a forma como o relatório é salvo, teremos que modificar essa classe, violando o SRP.
class RelatorioDAO {
public void salvarNoBanco() {
System.out.println("Salvando no banco de dados...");
}
}
Isso significa que podemos adicionar novas funcionalidades sem modificar o código existente.
Problema: Se precisarmos adicionar um novo cargo, teremos que modificar essa classe, o que pode gerar bugs.
class CalculadoraSalario {
public double calcularSalario(RegraDeCalculo regra, double salarioBase) {
return regra.calcular(salarioBase);
}
}
Agora, para adicionar um novo cargo, basta criar uma nova classe sem modificar o código existente!
class Ave { }
Isso significa que interfaces grandes devem ser divididas em interfaces menores.
Problema: Nem todos os funcionários recebem comissão, mas são obrigados a implementar receberComissao().
Código corrigido (seguindo o ISP)
interface Funcionario {
void calcularSalario();
void baterPonto();
}
interface Comissionado {
void receberComissao();
}
Isso significa que devemos evitar dependências diretas de classes concretas, e preferir depender de interfaces ou classes
abstratas.
class Carro {
private Motor motor = new Motor(); // DEPENDÊNCIA DIRETA
Problema: Se quisermos trocar o motor por um MotorEletrico, teremos que modificar Carro.
class Carro {
private Motor motor;
Conclusão
Os princípios SOLID ajudam a criar sistemas mais organizados, flexíveis e fáceis de manter.
Se quiser aprofundar em algum princípio, me avise!
6. Padrões de Projeto (Design Patterns)
Os padrões de projeto são soluções reutilizáveis para problemas comuns no desenvolvimento de software.
Eles ajudam a organizar o código, reduzir acoplamento e melhorar a manutenção do sistema.
6.1.1 - Singleton
Garante que uma classe tenha apenas uma instância no sistema e fornece um ponto global de acesso a ela.
Problema: Toda vez que criarmos um novo objeto ConexaoBanco, será uma nova conexão.
6.2.1 - Adapter
Permite que duas classes incompatíveis trabalhem juntas.
class TomadaEUA {
public void plugIn() {
System.out.println("Plugged into US outlet!");
}
}
Problema: Os métodos conectar() e plugIn() são diferentes, então não podemos usá-los de forma intercambiável.
@Override
public void conectar() {
tomadaEUA.plugIn();
}
}
6.3.1 - Observer
Permite que objetos sejam notificados quando outro objeto mudar de estado.
class Canal {
private List<Observador> observadores = new ArrayList<>();
class Pagamento {
private EstrategiaPagamento estrategia;
Agora podemos trocar a forma de pagamento sem modificar o código da classe Pagamento!
Conclusão
Os Padrões de Projeto ajudam a criar software mais modular, reutilizável e flexível.
Se quiser aprofundar em algum padrão, me avise!
7. Princípios SOLID
Os princípios SOLID foram criados por Robert C. Martin (Uncle Bob) e são um conjunto de cinco diretrizes que ajudam a
escrever um código mais limpo, coeso e desacoplado.
Problema:
A classe Relatorio está fazendo três coisas diferentes:
1. Gerando um relatório
2. Salvando no banco
3. Enviando e-mail
Isso quebra o SRP, pois se a regra de envio de e-mail mudar, temos que alterar essa classe, mesmo que o relatório não tenha
mudado.
class BancoDeDados {
public void salvar(String dados) {
System.out.println("Salvando no banco: " + dados);
}
}
class EmailService {
public void enviar(String destinatario, String conteudo) {
System.out.println("Enviando e-mail para " + destinatario);
}
}
Problema:
Se precisarmos adicionar uma nova operação (por exemplo, potência ^), temos que modificar essa classe, quebrando o
princípio OCP.
class Calculadora {
public double calcular(Operacao operacao, double a, double b) {
return operacao.executar(a, b);
}
}
Problema:
Se chamarmos pinguim.voar(), ele herdou um comportamento que não faz sentido!
Agora respeitamos o LSP e não temos aves que "voam" sem poder voar!
7.4 - Interface Segregation Principle (ISP)
Uma interface não deve forçar a implementação de métodos que a classe não precisa.
interface Motorista {
void dirigir();
}
class Computador {
private Teclado teclado = new Teclado(); // Forte acoplamento!
Problema:
A classe Computador depende diretamente de Teclado, tornando difícil mudar para outro tipo de entrada (como um mouse).
class Computador {
private DispositivoEntrada dispositivo;
Conclusão
Os princípios SOLID tornam o código mais organizado, modular e flexível. Aplicá-los corretamente melhora a
manutenção, reutilização e escalabilidade do software!
8. Relacionamentos entre Classes
Os relacionamentos entre classes definem como os objetos interagem e se conectam dentro de um sistema orientado a
objetos. Eles são fundamentais para criar um design limpo, coeso e reutilizável.
8.1 - Associação
A associação representa um vínculo entre duas classes.
class Pedido {
private Cliente cliente; // Pedido conhece Cliente
Explicação:
• A classe Pedido conhece Cliente, mas Cliente não conhece Pedido.
• Essa é uma associação unidirecional.
Exemplo de Associação Bidirecional
class Cliente {
private String nome;
private Pedido pedido; // Cliente agora conhece Pedido
class Pedido {
private Cliente cliente;
Explicação:
• Agora Cliente e Pedido se conhecem.
• Se precisarmos do pedido a partir do cliente, podemos acessar cliente.getPedido().
8.2 - Agregação
A agregação é uma relação "tem um", onde uma classe pode existir independentemente da outra.
Exemplo: Um "Curso" tem vários "Alunos", mas se o curso for encerrado, os alunos continuam existindo.
Exemplo de Agregação
import java.util.ArrayList;
import java.util.List;
class Aluno {
private String nome;
class Curso {
private String nome;
private List<Aluno> alunos = new ArrayList<>();
curso.listarAlunos();
}
}
Explicação:
• Curso tem vários Aluno, mas Aluno pode existir sem Curso.
• Se o curso for excluído, os alunos não desaparecem.
8.3 - Composição
A composição é uma relação "parte de", onde uma classe depende totalmente da outra para existir.
Exemplo: Um "Carro" tem um "Motor". Se o carro for destruído, o motor também deixa de existir.
Exemplo de Composição
class Motor {
private String tipo;
class Carro {
private String modelo;
private Motor motor; // Composição: o Motor é parte do Carro
Explicação:
• Motor só existe se houver um Carro.
• Se Carro for destruído, Motor também é destruído.
8.4 - Herança
Herança é uma relação "é um".
Exemplo de Herança
class Animal {
public void fazerSom() {
System.out.println("Som genérico de animal");
}
}
Explicação:
• Cachorro herda os comportamentos de Animal.
• Podemos sobrescrever (@Override) métodos para especializar o comportamento.
8.5 - Dependência
Uma classe depende temporariamente de outra para executar uma ação.
Exemplo de Dependência
class Pagamento {
public void processarPagamento() {
System.out.println("Pagamento processado!");
}
}
class Cliente {
public void pagar(Pagamento pagamento) {
pagamento.processarPagamento();
}
}
cliente.pagar(pagamento);
}
}
Explicação:
• Cliente usa Pagamento, mas não mantém uma referência fixa.
Conclusão
Os relacionamentos entre classes são essenciais para modelar sistemas de forma eficiente. Cada tipo de relação tem um
propósito específico e deve ser usado corretamente para garantir um código modular, reutilizável e flexível!
9. Polimorfismo
O polimorfismo é um dos pilares fundamentais da programação orientada a objetos (POO). Ele permite que um mesmo
método ou comportamento seja implementado de diferentes formas em diferentes classes.
O que é o Polimorfismo?
A palavra "polimorfismo" vem do grego e significa "muitas formas". Na prática, significa que um mesmo método pode se
comportar de maneiras diferentes dependendo do contexto.
Tipos de Polimorfismo
O polimorfismo pode ser dividido em duas categorias principais:
• Polimorfismo de Sobrecarga (Compile-time ou Estático)
• Polimorfismo de Substituição (Override ou Runtime ou Dinâmico)
// Método para somar três números inteiros (mesmo nome, parâmetros diferentes)
public int somar(int a, int b, int c) {
return a + b + c;
}
Explicação:
• O método somar tem três versões diferentes, cada uma com uma assinatura única.
• O compilador decide qual versão chamar com base nos argumentos passados.
• Esse tipo de polimorfismo ocorre em tempo de compilação (compile-time polymorphism).
9.2 - Polimorfismo de Substituição (Override)
Permite que uma subclasse modifique um método herdado de sua superclasse para fornecer uma implementação
específica.
Explicação:
• Cachorro e Gato herdam de Animal e sobrescrevem o método fazerSom().
• Mesmo que as variáveis meuAnimal1 e meuAnimal2 sejam do tipo Animal, o método específico da subclasse é
chamado.
• Isso acontece porque, em tempo de execução, o Java verifica o tipo real do objeto.
• Esse tipo de polimorfismo ocorre em tempo de execução (runtime polymorphism).
9.3 - Polimorfismo com Interfaces
O polimorfismo também pode ser usado com interfaces, permitindo que diferentes classes implementem a mesma interface
de formas distintas.
pagamento1.realizarPagamento(100.0);
pagamento2.realizarPagamento(50.0);
}
}
Explicação:
• CartaoCredito e Pix implementam a interface Pagamento.
• Podemos criar uma variável Pagamento e atribuir a ela qualquer classe que implemente essa interface.
• Isso permite flexibilidade e modularidade no código.
Conclusão
O polimorfismo é uma das características mais poderosas da POO! Ele permite criar código mais modular, reutilizável e
flexível, garantindo que métodos possam se comportar de maneiras diferentes dependendo do contexto.
Esse conceito garante segurança, organização e modularidade no código, permitindo que os dados internos de um objeto
não sejam acessados ou modificados diretamente, mas sim através de métodos controlados.
O que é Encapsulamento?
O encapsulamento é o princípio de restringir o acesso direto aos dados internos de um objeto e permitir a interação
apenas por meio de métodos específicos.
Em Java, ele é implementado utilizando modificadores de acesso (private, protected, public) e métodos getter e setter para
controlar a leitura e escrita dos atributos.
Vantagens do Encapsulamento:
Proteção dos dados internos contra acessos indevidos.
Maior controle sobre como os atributos são alterados.
Redução do acoplamento entre classes.
Facilidade na manutenção e evolução do código.
Exemplo de Encapsulamento
class ContaBancaria {
// Atributos privados (não podem ser acessados diretamente)
private String titular;
private double saldo;
// Construtor
public ContaBancaria(String titular, double saldoInicial) {
this.titular = titular;
this.saldo = saldoInicial;
}
// Realizando operações
conta.depositar(500);
conta.sacar(300);
conta.sacar(1500); // Tentativa de saque inválida
Explicação:
• Os atributos são privados (private), impedindo acesso direto.
• Os métodos get e set controlam o acesso aos atributos.
• O saldo não pode ser alterado diretamente, apenas pelos métodos depositar() e sacar().
• O código fica mais seguro e controlado, pois o usuário não pode inserir valores inválidos diretamente.
Explicação:
• marca é protected, então a subclasse Carro pode acessá-lo.
• Se marca fosse private, Carro não poderia acessá-lo diretamente.
Conclusão
O encapsulamento é fundamental na POO, pois protege os dados, melhora a organização e facilita a manutenção do código.
O que é Herança?
A herança estabelece uma relação "é um" entre classes.
Ou seja, se temos uma classe Animal, podemos ter subclasses como Cachorro e Gato, pois ambos são animais.
Explicação:
• A classe Animal tem um atributo nome e um método fazerSom().
• A classe Cachorro herda (extends Animal), então pode usar os métodos e atributos da superclasse.
• Além disso, Cachorro tem seu próprio método abanarRabo().
11.2 - Construtores e Herança
A subclasse não herda automaticamente o construtor da superclasse, mas pode chamá-lo usando super().
// Construtor da Superclasse
public Animal(String nome) {
this.nome = nome;
}
// Subclasse
class Cachorro extends Animal {
String raca;
Explicação:
• super(nome) chama o construtor da superclasse Animal.
• Assim, a subclasse Cachorro não precisa reescrever código para inicializar nome.
11.3 - Herança e Modificadores de Acesso
Modificador Pode ser herdado? Pode ser acessado diretamente pela subclasse?
private Não Não
default Sim Não (exceto se estiver no mesmo pacote)
protected Sim Sim
public Sim Sim
Se um atributo ou método for private, a subclasse não pode acessá-lo diretamente, mas pode usar métodos public ou
protected da superclasse.
Explicação:
• nome está como protected, então Gato pode acessá-lo diretamente.
11.4 - Sobrescrita de Métodos (Override)
A subclasse pode modificar o comportamento de um método herdado usando @Override.
Explicação:
• O método fazerSom() foi sobrescrito em Cachorro.
• Mesmo que meuAnimal seja do tipo Animal, ele chama a versão de Cachorro.
11.5 - Herança Múltipla
Em Java, não existe herança múltipla de classes (uma classe não pode herdar de duas classes ao mesmo tempo). Isso evita o
problema do "diamante".
interface Carnivoro {
void comerCarne();
}
@Override
public void comerCarne() {
System.out.println("O leão come carne.");
}
}
Explicação:
• Leao implementa duas interfaces (Mamifero e Carnivoro).
• Como interfaces não possuem implementação, não há conflito de código.
Conclusão
A herança permite reutilizar código e organizar o sistema em uma hierarquia lógica.
Resumo:
• A subclasse herda atributos e métodos da superclasse (extends).
• O construtor da superclasse pode ser chamado com super().
• Métodos podem ser sobrescritos (@Override).
• Java não suporta herança múltipla de classes, mas suporta herança de múltiplas interfaces.
Usada corretamente, a herança torna o código mais eficiente, reutilizável e fácil de manter!
12. Polimorfismo
O polimorfismo é um dos quatro pilares da Programação Orientada a Objetos (POO), junto com abstração, encapsulamento
e herança. Ele permite que um mesmo método possa ter diferentes comportamentos, tornando o código mais flexível,
reutilizável e extensível.
O que é Polimorfismo?
Explicação:
• Os métodos somar possuem o mesmo nome, mas assinaturas diferentes.
• O compilador escolhe automaticamente qual método chamar com base nos parâmetros passados.
Vantagens da Sobrecarga:
Permite criar várias versões do mesmo método.
Melhora a legibilidade e organização do código.
Evita nomes de métodos diferentes para funções semelhantes.
12.2 - Polimorfismo de Sobrescrita (Method Overriding)
Ocorre quando um método de uma superclasse é redefinido (sobrescrito) em uma subclasse.
Explicação:
• A superclasse Animal tem um método fazerSom().
• Cachorro e Gato sobrescrevem esse método com sua própria implementação.
• Mesmo que meuAnimal seja do tipo Animal, ele se comporta como Cachorro ou Gato em tempo de execução.
Regras da Sobrescrita:
O método na subclasse deve ter o mesmo nome, tipo de retorno e parâmetros.
Deve ter a mesma ou maior visibilidade (exemplo: protected → public).
Métodos private e static não podem ser sobrescritos.
12.3 - Polimorfismo com Classes Abstratas
Se uma classe contém métodos abstratos, as subclasses devem sobrescrevê-los.
Explicação:
• Animal é uma classe abstrata, então não pode ser instanciada diretamente.
• Cavalo é obrigado a implementar o método fazerSom().
Conclusão
O polimorfismo é essencial para criar programas modulares e reutilizáveis.
Resumo:
• Polimorfismo de Sobrecarga (Overloading) → Mesmo nome, diferentes assinaturas (resolvido em tempo de
compilação).
• Polimorfismo de Sobrescrita (Overriding) → Mesmo nome, mesma assinatura, mas implementação diferente
(resolvido em tempo de execução).
• Pode ser aplicado em classes, classes abstratas e interfaces.
O polimorfismo permite que um código seja reutilizado sem perder flexibilidade, tornando o design do sistema mais
organizado, escalável e fácil de manter!
13. Classe Abstrata
A classe abstrata é um conceito fundamental da Programação Orientada a Objetos (POO) que permite a criação de uma
estrutura de código mais flexível e reutilizável. Ela serve como um modelo base para outras classes, mas não pode ser
instanciada diretamente. Seu principal objetivo é definir um comportamento comum para classes derivadas.
Uma classe abstrata é uma classe que não pode ser instanciada diretamente e pode conter métodos abstratos (sem
implementação) e métodos concretos (com implementação).
Ela força as subclasses a fornecerem implementações específicas para seus métodos abstratos.
Pode conter métodos abstratos (sem corpo) e métodos concretos (com corpo).
Não pode ser instanciada diretamente.
Pode ter construtores, mas apenas para ser chamado pelas subclasses.
Pode conter atributos e métodos comuns para todas as subclasses.
Pode implementar interfaces e ter métodos estáticos.
13.1 - Exemplo Simples de Classe Abstrata
Um método abstrato é um método que não possui implementação na classe abstrata e deve ser implementado por qualquer
subclasse concreta.
abstract class Veiculo {
abstract void acelerar();
}
Além de métodos abstratos, uma classe abstrata pode conter métodos concretos (com implementação).
Isso é útil quando queremos fornecer uma implementação padrão que pode ser usada diretamente ou sobrescrita pelas
subclasses.
abstract class Computador {
abstract void ligar();
// Método concreto
public void exibirMarca() {
System.out.println("Este computador é da marca Genérica.");
}
}
Métodos concretos Sim Não (apenas a partir do Java 8 com métodos default)
Herança múltipla Não Sim (uma classe pode implementar várias interfaces)
Vamos supor que estamos construindo um sistema de pagamentos que pode ter Cartão de Crédito e Pix.
abstract class Pagamento {
double valor;
@Override
void realizarPagamento() {
System.out.println("Pagamento via Cartão de Crédito: R$" + valor);
}
}
@Override
void realizarPagamento() {
System.out.println("Pagamento via Pix: R$" + valor);
}
}
public class Main {
public static void main(String[] args) {
Pagamento pagamento1 = new PagamentoCartao(100);
pagamento1.realizarPagamento();
pagamento1.imprimirRecibo();
Explicação do código:
Conclusão
As classes abstratas são uma ferramenta poderosa para estruturar e reutilizar código em Java.
Principais pontos:
Forçam as subclasses a implementar métodos específicos.
Permitem compartilhar atributos e métodos comuns.
Ajudam a organizar o código seguindo um modelo hierárquico.
São ideais quando há um comportamento base, mas a implementação varia.
Em resumo: Se você precisa de um esqueleto comum para várias classes, mas quer que elas implementem seus próprios
comportamentos específicos, use classes abstratas!
Fala, Dev! Parabéns por ter chegado até nos estudos. Espero que esse material te faça crescer como profissional e você atinja
seus objetivos. Aproveito o momento e o convido para conhecer minhas redes sociais onde terá acesso a mais conteúdos como
esse:
Conteúdo desenvolvido por: Olival Paulino
Canal do Youtube: https://youtube.com/@olivalpaulino
Instagram: https://www.instagram.com/olivalpaulino/
Aproveito também e deixo o link de todos os meus cursos, para que você os conheça e possa acelerar ainda mais os seus
estudos, seja na teoria, na prática, criando projetos, e aplicando todos os conceitos principais na prática, seja criando aplicações
desktop ou web, ou ainda, aplicações back-end ou full stack java. Conheça-os abaixo: