어그리게이션 vs 컴포지션
Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 87개 중 48번째.
both aggregation과 composition은 모두 "has-a" 관계의 형태이지만, 한 가지 중요한 측면인 소유권과 생명 주기 의존성에서 차이가 있습니다.
composition에서는 포함된 객체가 컨테이너와 independently 존재할 수 없습니다. 컨테이너가 소멸하면 그 부분들도 함께 소멸합니다. House와 그 Room 객체를 생각해 보세요. 집이 없으면 방도 존재하지 않습니다:
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가 rooms를 생성하고 소유합니다
}
}
}aggregation에서는 포함된 객체가 독립적으로 존재할 수 있습니다. 컨테이너는 객체를 사용하지만 객체의 생명 주기를 제어하지는 않습니다. Team과 그 Player 객체를 생각해 보세요. 플레이어는 팀이 없어도 존재합니다:
class Team {
private List<Player> players;
public Team() {
players = new ArrayList<>();
}
public void addPlayer(Player player) {
players.add(player); // Team은 기존 플레이어를 사용합니다
}
}핵심적인 차이점은 다음과 같습니다. 컴포지션에서는 컨테이너가 내부적으로 구성 요소를 생성합니다. 집계에서는 객체가 외부에서 전달됩니다. Team이 삭제되어도 Player 객체는 여전히 존재합니다. House가 삭제되면 its Room 객체도 사라집니다.
챌린지
쉬움aggregation과 composition을 모두 보여 주는 대학 과정 시스템을 만들어 봅시다. Course가 자신의 Lecture 객체를 소유하는 방식(composition)과, 독립적으로 존재하는 Professor 객체를 참조만 하는 방식(aggregation)을 확인할 수 있습니다.
코드를 네 개의 파일로 구성합니다:
Professor.java: 어떤 Course와도 독립적으로 존재할 수 있는 교수를 나타내는 class를 만듭니다. Professor에는 두 개의 private fields가 있습니다:name(String)과department(String)입니다. 두 fields를 초기화하는 constructor와 각각에 대한 getter 메서드를 포함하세요.toString()을 재정의하여 다음을 반환하도록 하세요:Prof. [name] ([department])Lecture.java: Course 내부에서만 의미가 있는 강의를 나타내는 class를 만듭니다. Lecture에는 두 개의 private fields가 있습니다:topic(String)과durationMinutes(int)입니다. constructor와 getter를 포함하세요.toString()을 재정의하여 다음을 반환하도록 하세요:Lecture: [topic] ([durationMinutes] min)Course.java: 여기에서 두 관계를 모두 보여 줍니다! Course에는 세 개의 private fields가 있습니다:title(String),professor(Professor - aggregation),lectures(Lecture 객체의 array - composition)입니다.constructor는 과정 제목, 외부에서 전달된 Professor 객체(aggregation), 그리고 lecture 수를 인수로 받습니다. constructor 내부에서 Lecture array를 만들고 새로운 Lecture 객체로 채우세요. 인덱스
i에 있는 Each lecture에 대해, topic은"Topic " + (i + 1)로, duration은45분으로 생성하세요. 이러한 내부 생성이 composition을 보여 줍니다.여러 줄의 String을 반환하는
getInfo()메서드를 추가하세요:Course: [title] Instructor: [professor.toString()] Lectures: [number of lectures]또한 각 lecture의 toString()을 자체 줄에 반환하는 String을 반환하는
listLectures()메서드도 추가하세요.Main.java: 모든 것을 하나로 연결합니다! 네 개의 입력을 받습니다: professor name (String), professor department (String), course title (String), number of lectures (int)입니다.먼저 주어진 name과 department로 Professor를 생성하세요. 이 Professor는 독립적으로 존재합니다. 그런 다음 title, Professor(aggregation), lecture count를 전달하여 Course를 생성하세요(Course는 내부적으로 자신의 lectures를 create합니다 - composition).
getInfo()의 결과를 출력한 다음, empty line을 출력하고, 이어서listLectures()의 결과를 출력하세요.
입력은 다음 순서로 네 개를 받습니다: professor name, department, course title, number of lectures입니다.
핵심적인 차이점에 주목하세요. Professor는 외부에서 생성되어 Course에 전달됩니다(aggregation: 해당 professor는 다른 Course를 가르치거나 이 Course 없이 존재할 수 있습니다). Lectures는 Course constructor 내부에서 생성됩니다(composition). Lectures는 이 Course에 독점적으로 속하며 이 Course 없이는 존재하지 않습니다.
직접 해보기
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 입력 읽기
String professorName = scanner.nextLine();
String department = scanner.nextLine();
String courseTitle = scanner.nextLine();
int numberOfLectures = scanner.nextInt();
// TODO: Professor 객체 생성 (독립적으로 존재 - 집합)
// TODO: Course 객체 생성, professor 전달 (집합)
// 코스가 내부적으로 자체 강의를 생성함 (구성)
// TODO: getInfo() 결과 출력
// TODO: 빈 줄 출력
// TODO: listLectures() 결과 출력
}
}이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
4상속
상속의 기초 (extends)super 키워드메서드 오버라이딩 (@Override)생성자 체이닝Object 클래스단일 및 다중 레벨 상속다중 클래스 상속이 불가능한 이유요약 - 직원 계층 구조직접 연습해 보세요: 온라인 Java 컴파일러