Menu
Coddy logo textTech

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 "has-a", mas elas diferem em um aspecto crucial: propriedade e dependência de 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 seus objetos Room—os quartos 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();  // A casa cria e possui os cômodos
        }
    }
}

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);  // A equipe 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 um Team é excluído, os objetos Player ainda existem. Quando uma House é excluída, seus objetos Room também desaparecem.

challenge icon

Desafio

Fácil

Vamos construir um sistema de cursos universitários que demonstra tanto agregação quanto composição. Você verá como um Course possui seus objetos Lecture (composição), enquanto apenas referencia objetos Professor que existem de forma independente (agregação).

Você organizará seu código em quatro arquivos:

  • Professor.java: Crie uma classe que representa um professor que pode existir independentemente de qualquer curso. Um Professor possui dois campos privados: name (String) e department (String). Inclua um construtor para inicializar ambos os campos e métodos getter para cada um. Sobrescreva toString() para retornar: "Prof. " + name + " (" + department + ")"
  • Lecture.java: Crie uma classe que representa uma palestra que só faz sentido dentro de um curso. Uma Lecture possui dois campos privados: topic (String) e durationMinutes (int). Inclua um construtor e getters. Sobrescreva toString() para retornar: "Lecture: " + topic + " (" + durationMinutes + " min)"
  • Course.java: É aqui que você demonstrará ambos os relacionamentos! Um Course possui três campos privados: title (String), professor (Professor - agregação) e lectures (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 palestras. Dentro do construtor, crie o array de Lecture e preencha-o com novos objetos Lecture. Para cada palestra no índice i, crie-a com o tópico "Topic " + (i + 1) e duração de 45 minutos. Essa criação interna demonstra composição.

    Adicione um método getInfo() que retorna uma String de várias linhas:

    Course: [title]
    Instructor: [professor.toString()]
    Lectures: [number of lectures]

    Adicione também um método listLectures() que retorna uma String com o toString() de cada palestra 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 palestras (int).

    Primeiro, crie um Professor com o nome e departamento fornecidos — este professor existe de forma independente. Em seguida, crie um Course, passando o título, o professor (agregação) e a contagem de palestras (o curso criará suas próprias palestras internamente - composição).

    Imprima o resultado de getInfo(), depois imprima uma linha vazia e, em seguida, imprima o resultado de listLectures().

Você receberá quatro entradas na ordem: nome do professor, departamento, título do curso e número de palestras.

Observe a diferença fundamental: o Professor é criado fora e passado para o Course (agregação — o professor poderia dar outros cursos ou existir sem este). As Lectures são criadas dentro do construtor do Course (composição — elas pertencem exclusivamente a este curso e não existiriam sem ele).

Folha de consulta

Tanto a agregação quanto a composição são relacionamentos do tipo "tem-um" que diferem na propriedade e na dependência do ciclo de vida.

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 destruídas. O contêiner cria suas partes internamente.

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 os quartos
        }
    }
}

Agregação: O objeto contido pode existir independentemente. O contêiner usa o objeto, mas não controla seu ciclo de vida. Os objetos são passados de fora.

class Team {
    private List<Player> players;
    
    public Team() {
        players = new ArrayList<>();
    }
    
    public void addPlayer(Player player) {
        players.add(player);  // Team usa jogadores existentes
    }
}

Distinção principal: Quando um contêiner é excluído, os objetos agregados ainda existem, mas os objetos compostos são destruídos.

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 curso criará suas próprias palestras internamente (composição)
        
        // TODO: Imprimir o resultado de getInfo()
        
        // TODO: Imprimir uma linha vazia
        
        // TODO: Imprimir o resultado de listLectures()
        
    }
}
quiz iconTeste seus conhecimentos

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