Menu
Coddy logo textTech

Cechy a dziedziczenie

Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 55 z 91.

Skoro już rozumiesz, jak działają cechy, wyjaśnijmy, kiedy używać cech, a kiedy dziedziczenia. Oba rozwiązania umożliwiają ponowne wykorzystanie kodu, ale służą różnym celom i mają odmienne właściwości.

Dziedziczenie ustanawia relację „jest”. Klasa Dog rozszerzająca Animal oznacza, że pies jest zwierzęciem. Klasa potomna dziedziczy tożsamość klasy nadrzędnej i może być używana wszędzie tam, gdzie oczekiwany jest typ klasy nadrzędnej.

Cechy zapewniają możliwość „posiadania”. Gdy klasa używa cechy Loggable, ma funkcjonalność logowania — ale nie staje się loggerem. Cechy dodają zachowanie, nie zmieniając tego, czym klasa zasadniczo jest.

<?php
// Dziedziczenie: Dog JEST obiektem typu Animal
class Animal {
    public function breathe(): void {
        echo "Breathing";
    }
}

class Dog extends Animal {
    public function bark(): void {
        echo "Woof!";
    }
}

// Cecha: Dog MA możliwość logowania
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}

Najważniejsze różnice do zapamiętania:

AspektDziedziczenieCechy
Relacjajest-rodzajemma możliwości
OgraniczenieTylko jedna klasa nadrzędnaDozwolonych jest wiele cech
Sprawdzanie typówDziała z instanceofBrak tożsamości typu
Najlepsze zastosowanieRelacje hierarchiczneWspólne zachowania w niezwiązanych ze sobą klasach

Używaj dziedziczenia, gdy klasy mają wspólną tożsamość. Używaj traitów, gdy niezwiązane ze sobą klasy potrzebują tej samej funkcjonalności, ale nie należą do tej samej hierarchii.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system pojazdów, który pokazuje, kiedy używać dziedziczenia, a kiedy traitów. Utworzysz hierarchię pojazdów o wspólnej tożsamości wynikającej z dziedziczenia, a jednocześnie dodasz przekrojowe możliwości za pomocą traitów.

Rozmieścisz kod w czterech plikach:

  • Trackable.php: Utwórz trait o nazwie Trackable, który zapewnia możliwość śledzenia GPS. Trait powinien zawierać:
    • Prywatną właściwość $location (string)
    • Metodę setLocation(string $location), która zapisuje bieżącą lokalizację
    • Metodę getLocation(), która zwraca "Location: [location]"
    Ten trait reprezentuje możliwość typu „ma”: każdy pojazd może mieć funkcję śledzenia, ale posiadanie funkcji śledzenia nie czyni czegoś pojazdem.
  • Vehicle.php: Utwórz bazową klasę Vehicle, która ustanawia relację typu „jest”. Dołącz plik traitu. Użyj promocji konstruktora, aby zdefiniować chronioną właściwość $brand. Dodaj metodę describe(), która zwraca "Vehicle: [brand]". Ta klasa powinna używać traitu Trackable, ponieważ wszystkie pojazdy w naszej flocie będą wyposażone w GPS.
  • Car.php: Utwórz klasę Car, która rozszerza Vehicle. Dołącz plik Vehicle. Użyj promocji konstruktora, aby przyjąć markę oraz prywatną właściwość $doors (liczba całkowita). Wywołaj konstruktor klasy nadrzędnej, przekazując markę. Nadpisz metodę describe(), aby zwracała "Car: [brand] with [doors] doors".
  • main.php: Dołącz plik Car. Otrzymasz trzy dane wejściowe: nazwę marki, liczbę drzwi i ciąg znaków określający lokalizację. Utwórz instancję Car, ustaw jej lokalizację, a następnie wypisz dwa wiersze:
    • Wynik wywołania describe()
    • Wynik wywołania getLocation()

Zwróć uwagę, jak współdziałają tu dziedziczenie i traity: Car jest Vehicle (dziedziczenie ustanawia tożsamość), a Vehicle ma funkcję śledzenia (trait dodaje zachowanie). Możesz użyć instanceof Vehicle, aby sprawdzić, czy coś jest pojazdem, ale nie istnieje typ „Trackable”, względem którego można by to sprawdzić: to kluczowa różnica między tymi dwoma podejściami.

Spróbuj swoich sił

<?php
// Plik główny - utwórz i przetestuj instancję Car

// TODO: Dołącz plik Car.php

// Odczytaj dane wejściowe
$brand = trim(fgets(STDIN));
$doors = intval(trim(fgets(STDIN)));
$location = trim(fgets(STDIN));

// TODO: Utwórz instancję Car z wartościami brand i doors

// TODO: Ustaw lokalizację samochodu

// TODO: Wyświetl wynik describe()

// TODO: Wyświetl wynik getLocation()
?>
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator PHP online