Agregação vs Composição
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 48 de 87.
Tanto a agregação quanto a composição são formas de relacionamentos "tem-um", mas diferem em um aspecto crucial: propriedade e dependência do ciclo de vida.
Na composição, o objeto contido não pode existir independentemente do contêiner. Quando o contêiner é destruído, suas partes também são. Pense em uma House e em seus objetos Room: os cômodos não existem sem a casa:
class House {
private Room[] rooms;
public House(int numRooms) {
rooms = new Room[numRooms];
for (int i = 0; i < numRooms; i++) {
rooms[i] = new Room(); // House cria e possui rooms
}
}
}Na agregação, o objeto contido pode existir de forma independente. O contêiner usa o objeto, mas não controla seu ciclo de vida. Considere um Team e seus objetos Player: os jogadores existem mesmo sem um time:
class Team {
private List<Player> players;
public Team() {
players = new ArrayList<>();
}
public void addPlayer(Player player) {
players.add(player); // Team usa jogadores existentes
}
}A distinção fundamental: na composição, o contêiner cria suas partes internamente. Na agregação, os objetos são passados de fora. Quando uma Team é excluída, os objetos Player ainda existem. Quando uma House é excluída, seus objetos Room também desaparecem.
Desafio
FácilVamos criar um sistema de cursos universitários que demonstre tanto agregação quanto composição. Você verá como um Course possui seus objetos Lecture (composição), enquanto apenas referencia objetos Professor que existem independentemente (agregação).
Você organizará seu código em quatro arquivos:
Professor.java: crie uma classe que represente um professor que pode existir independentemente de qualquer curso. Um Professor tem dois campos privados:name(String) edepartment(String). Inclua um construtor para inicializar ambos os campos e métodos getter para cada um deles. SubstituatoString()para retornar:Prof. [name] ([department])Lecture.java: crie uma classe que represente uma aula que só faz sentido dentro de um curso. Uma Lecture tem dois campos privados:topic(String) edurationMinutes(int). Inclua um construtor e getters. SubstituatoString()para retornar:Lecture: [topic] ([durationMinutes] min)Course.java: é aqui que você demonstrará ambas as relações! Um Course tem três campos privados:title(String),professor(Professor - agregação) electures(um array de objetos Lecture - composição).O construtor recebe o título do curso, um objeto Professor (passado de fora - agregação) e o número de aulas. Dentro do construtor, crie o array de Lecture e preencha-o com novos objetos Lecture. Para cada aula no índice
i, crie-a com o tópico"Topic " + (i + 1)e duração de45minutos. Essa criação interna demonstra a composição.Adicione um método
getInfo()que retorne uma String com várias linhas:Course: [title] Instructor: [professor.toString()] Lectures: [number of lectures]Adicione também um método
listLectures()que retorne uma String com o toString() de cada aula em sua própria linha.Main.java: reúna tudo! Você receberá quatro entradas: nome do professor (String), departamento do professor (String), título do curso (String) e número de aulas (int).Primeiro, crie um Professor com o nome e o departamento fornecidos. Esse professor existe independentemente. Em seguida, crie um Course, passando o título, o professor (agregação) e a quantidade de aulas (o curso criará suas próprias aulas internamente - composição).
Imprima o resultado de
getInfo(), depois imprima uma linha vazia e, em seguida, imprima o resultado delistLectures().
Você receberá quatro entradas nesta ordem: nome do professor, departamento, título do curso e número de aulas.
Observe a principal diferença: o Professor é criado fora e passado para o Course (agregação: o professor poderia ministrar outros cursos ou existir sem este curso). As Lectures são criadas dentro do construtor de Course (composição. Elas pertencem exclusivamente a este curso e não existiriam sem ele).
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler entradas
String professorName = scanner.nextLine();
String department = scanner.nextLine();
String courseTitle = scanner.nextLine();
int numberOfLectures = scanner.nextInt();
// TODO: Criar um objeto Professor (existe independentemente - agregação)
// TODO: Criar um objeto Course, passando o professor (agregação)
// O course criará suas próprias lectures internamente (composição)
// TODO: Imprimir o resultado de getInfo()
// TODO: Imprimir uma linha vazia
// TODO: Imprimir o resultado de listLectures()
}
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online