Agregacja a kompozycja
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 48 z 87.
Zarówno agregacja, jak i kompozycja są formami relacji „ma”, ale różnią się pod jednym kluczowym względem: własnością i zależnością cyklu życia.
W kompozycji zawarty obiekt nie może istnieć niezależnie od kontenera. Gdy kontener zostaje zniszczony, jego części również. Pomyśl o obiektach House i Room: pokoje nie istnieją bez domu:
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 tworzy pokoje i jest ich właścicielem
}
}
}W przypadku agregacji zawarty obiekt może istnieć niezależnie. Kontener używa obiektu, ale nie kontroluje jego cyklu życia. Rozważmy Team i jego obiekty Player: gracze istnieją nawet bez drużyny:
class Team {
private List<Player> players;
public Team() {
players = new ArrayList<>();
}
public void addPlayer(Player player) {
players.add(player); // Team korzysta z istniejących graczy
}
}Kluczowa różnica: w kompozycji kontener tworzy swoje części wewnętrznie. W agregacji obiekty są przekazywane z zewnątrz. Gdy Team zostaje usunięty, obiekty Player nadal istnieją. Gdy House zostaje usunięty, jego obiekty Room również znikają.
Wyzwanie
ŁatwyZbudujmy system kursów uniwersyteckich, który demonstruje zarówno agregację, jak i kompozycję. Zobaczysz, jak Course posiada obiekty Lecture (kompozycja), a jednocześnie jedynie odwołuje się do obiektów Professor, które istnieją niezależnie (agregacja).
Rozmieścisz swój kod w czterech plikach:
Professor.java: Utwórz klasę reprezentującą profesora, który może istnieć niezależnie od dowolnego kursu. Profesor ma dwa prywatne pola:name(String) idepartment(String). Dodaj konstruktor inicjalizujący oba pola oraz metody pobierające wartość każdego z nich. NadpisztoString(), aby zwracała:Prof. [name] ([department])Lecture.java: Utwórz klasę reprezentującą wykład, który ma sens tylko w ramach kursu. Wykład ma dwa prywatne pola:topic(String) idurationMinutes(int). Dodaj konstruktor i metody pobierające wartości pól. NadpisztoString(), aby zwracała:Lecture: [topic] ([durationMinutes] min)Course.java: To tutaj zademonstrujesz obie relacje! Kurs ma trzy prywatne pola:title(String),professor(Professor — agregacja) orazlectures(tablica obiektów Lecture — kompozycja).Konstruktor przyjmuje tytuł kursu, obiekt Professor (przekazany z zewnątrz — agregacja) oraz liczbę wykładów. Wewnątrz konstruktora utwórz tablicę Lecture i wypełnij ją nowymi obiektami Lecture. Dla każdego wykładu o indeksie
iutwórz go z tematem"Topic " + (i + 1)i czasem trwania45minut. To tworzenie wewnątrz klasy demonstruje kompozycję.Dodaj metodę
getInfo(), która zwraca wielowierszowy String:Course: [title] Instructor: [professor.toString()] Lectures: [number of lectures]Dodaj także metodę
listLectures(), która zwraca String zawierający wynik toString() każdego wykładu w osobnym wierszu.Main.java: Połącz wszystkie elementy! Otrzymasz cztery dane wejściowe: imię i nazwisko profesora (String), wydział profesora (String), tytuł kursu (String) oraz liczbę wykładów (int).Najpierw utwórz obiekt Professor z podanym imieniem i nazwiskiem oraz wydziałem. Ten profesor istnieje niezależnie. Następnie utwórz obiekt Course, przekazując mu tytuł, profesora (agregacja) i liczbę wykładów (kurs utworzy własne wykłady wewnętrznie — kompozycja).
Wypisz wynik
getInfo(), następnie pusty wiersz, a potem wyniklistLectures().
Otrzymasz kolejno cztery dane wejściowe: imię i nazwisko profesora, wydział, tytuł kursu oraz liczbę wykładów.
Zwróć uwagę na kluczową różnicę: obiekt Professor jest tworzony na zewnątrz i przekazywany do obiektu Course (agregacja: profesor mógłby prowadzić inne kursy lub istnieć bez tego kursu). Obiekty Lecture są tworzone wewnątrz konstruktora Course (kompozycja). Należą wyłącznie do tego kursu i nie istniałyby bez niego.
Spróbuj swoich sił
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Odczytaj dane wejściowe
String professorName = scanner.nextLine();
String department = scanner.nextLine();
String courseTitle = scanner.nextLine();
int numberOfLectures = scanner.nextInt();
// TODO: Utwórz obiekt Professor (istnieje niezależnie — agregacja)
// TODO: Utwórz obiekt Course, przekazując mu obiekt Professor (agregacja)
// Kurs utworzy własne wykłady wewnętrznie (kompozycja)
// TODO: Wypisz wynik getInfo()
// TODO: Wypisz pustą linię
// TODO: Wypisz wynik listLectures()
}
}Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online