Kompozycja a dziedziczenie
Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 56 z 91.
W poprzednim rozdziale dowiedziałeś się, że cechy zapewniają możliwość „ma”, podczas gdy dziedziczenie ustanawia relację „jest”. Kompozycja rozwija koncepcję „ma”, budując złożone obiekty z prostszych i przechowując je jako właściwości zamiast po nich dziedziczyć.
Przy dziedziczeniu Car może rozszerzać Vehicle. Przy kompozycji Car zawiera obiekt Engine:
<?php
class Engine {
public function start(): string {
return "Engine started";
}
}
class Car {
private Engine $engine;
public function __construct() {
$this->engine = new Engine();
}
public function start(): string {
return $this->engine->start();
}
}
$car = new Car();
echo $car->start();
Wynik:
Engine startedKlasa Car nie dziedziczy po Engine — posiada go. Takie podejście ma istotne zalety: możesz wymienić silnik na inną implementację, klasy pozostają luźno powiązane, a Ty unikasz sztywnych hierarchii tworzonych przez głębokie dziedziczenie.
Popularna zasada w OOP brzmi: „przedkładaj kompozycję nad dziedziczenie”. Dziedziczenie sprawdza się w przypadku rzeczywistych hierarchii typów (pies rzeczywiście jest zwierzęciem), ale kompozycja sprawdza się lepiej, gdy składasz funkcjonalność z niezależnych elementów. Możesz łączyć wiele obiektów, zastępować je w czasie działania programu i testować komponenty w izolacji.
W następnej lekcji omówimy wstrzykiwanie zależności, które rozwija kompozycję, umożliwiając kontrolowanie sposobu, w jaki obiekty otrzymują swoje zależności.
Wyzwanie
ŁatwyZbudujmy system komputerowy przy użyciu kompozycji, w której obiekt Computer składa się z osobnych obiektów komponentów, zamiast po nich dziedziczyć. To pokazuje, jak kompozycja pozwala budować złożone obiekty z prostszych, niezależnych części.
Rozmieścisz swój kod w trzech plikach:
Processor.php: Utwórz klasęProcessor, która reprezentuje procesor. Użyj promocji właściwości konstruktora, aby zdefiniować prywatne$model(ciąg znaków) i prywatne$cores(liczbę całkowitą). Dodaj metodęgetSpecs(), która zwraca"[model] ([cores] cores)".Memory.php: Utwórz klasęMemory, która reprezentuje pamięć RAM. Użyj promocji właściwości konstruktora, aby zdefiniować prywatne$size(liczbę całkowitą reprezentującą GB). Dodaj metodęgetCapacity(), która zwraca"[size]GB RAM".main.php: Dołącz oba pliki komponentów i utwórz klasęComputer, która wykorzystuje kompozycję. KlasaComputerpowinna:- Przechowywać obiekt
Processori obiektMemoryjako prywatne właściwości - Przyjmować w konstruktorze model procesora, liczbę rdzeni i rozmiar pamięci
- Tworzyć obiekty komponentów wewnętrznie podczas konstruowania
- Mieć metodę
describe(), która zwraca"Computer with [processor specs] and [memory capacity]"
Otrzymasz trzy dane wejściowe: model procesora, liczbę rdzeni i rozmiar pamięci w GB. Utwórz obiekt
Computero tych specyfikacjach i wypisz wynik wywołaniadescribe().- Przechowywać obiekt
Zwróć uwagę, że klasa Computer nie rozszerza klasy Processor ani Memory. Ona je zawiera. Ta relacja „ma” realizowana za pomocą kompozycji pozwala zachować niezależność i możliwość ponownego użycia każdego komponentu, a jednocześnie umożliwia klasie Computer delegowanie zadań do jej części w razie potrzeby.
Spróbuj swoich sił
<?php
require_once 'Processor.php';
require_once 'Memory.php';
class Computer
{
// TODO: Zdefiniuj prywatne właściwości do przechowywania obiektów Processor i Memory
// TODO: Konstruktor powinien przyjmować model procesora, liczbę rdzeni i rozmiar pamięci
// oraz tworzyć wewnętrznie obiekty komponentów
public function __construct()
{
// TODO: Utwórz obiekty Processor i Memory oraz zapisz je
}
// TODO: Zaimplementuj metodę describe(), która zwraca
// "Computer with [processor specs] and [memory capacity]"
public function describe(): string
{
// TODO: Wywołaj metody obiektów komponentów i zwróć sformatowany ciąg znaków
}
}
// Odczytaj dane wejściowe
$processorModel = trim(fgets(STDIN));
$cores = intval(fgets(STDIN));
$memorySize = intval(fgets(STDIN));
// TODO: Utwórz obiekt Computer o podanych parametrach i wypisz wynik describe()
?>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 $thisMetodyWłaściwościKonstruktor (__construct)Destruktor (__destruct)Powtórka — prosty kalkulator4Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe parent::Przesłanianie metodSłowo kluczowe finalKlasy abstrakcyjnePowtórzenie – hierarchia pracowników7Enkapsulacja
Public, protected, privateModyfikatory dostępu w szczegółachGettery i setteryUkrywanie informacjiPromocja parametrów konstruktora (8.0)Podsumowanie — system ewidencji studentów10Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieWstrzykiwanie zależnościKlasy anonimoweEnumy (PHP 8.1)Włókna (PHP 8.1)Dogłębne omówienie klonowania obiektówGeneratory i iteratory2Przestrzenie nazw i autoloading
Wprowadzenie do przestrzeni nazwSłowo kluczowe useStandard autoloadingu PSR-4Autoloader ComposeraPodsumowanie – uporządkowany projekt5Interfejsy i kontrakty
Wprowadzenie do interfejsówImplementowanie interfejsówImplementowanie wielu interfejsówInterfejs a klasa abstrakcyjnaPodpowiadanie typów za pomocą interfejsówPodsumowanie — kalkulator kształtów8Metody magiczne
Wprowadzenie do metod magicznych__toString i __debugInfo__get, __set, __isset, __unset__call i __callStatic__clone i klonowanie obiektów__serialize i __unserializePodsumowanie — własna kolekcja11System typów i obsługa błędów
Deklaracje typówTypy nullableTypy sumy i przecięciaKlasy wyjątkówNiestandardowa hierarchia wyjątkówTry, Catch, FinallyPodsumowanie — walidator formularzy14Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Właściwości klas
Właściwości instancji a właściwości statyczneStałe w klasachMetody i właściwości statyczneWłaściwości prywatne i chronioneWłaściwości tylko do odczytu (PHP 8.1)Podsumowanie — menedżer kont bankowych6Polimorfizm
Ponowne omówienie nadpisywania metodPolimorfizm za pomocą interfejsówPodpowiedzi typów i typy sumyPóźne wiązanie statycznePodsumowanie — procesor płatności9Cechy
Wprowadzenie do cechKorzystanie z wielu cechRozwiązywanie konfliktów cechMetody abstrakcyjne w cechachCechy a dziedziczenie12Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator PHP online