Implementowanie a rozszerzanie
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 47 z 110.
Skoro rozumiesz już zarówno extends, jak i implements, wyjaśnijmy, kiedy używać każdego z nich.
Używaj extends, gdy chcesz dziedziczyć zachowanie. Twoja podklasa otrzymuje cały kod klasy nadrzędnej za darmo i może go rozbudowywać:
class Animal {
void breathe() {
print('Breathing...');
}
}
class Dog extends Animal {
void bark() {
print('Woof!');
}
}
void main() {
var dog = Dog();
dog.breathe(); // Odziedziczone - działa automatycznie
dog.bark();
}Użyj implements, gdy chcesz zagwarantować strukturę bez dziedziczenia kodu. Każdą metodę musisz napisać samodzielnie:
class Robot implements Animal {
@override
void breathe() {
print('Ventilating circuits...'); // Implementacja całkowicie niestandardowa
}
}Kluczowa różnica: extends oznacza „jestem typem tego”, a implements — „potrafię robić to, co to”. Dog jest Animal i oddycha w ten sam sposób. Robot nie jest zwierzęciem, ale może spełniać ten sam kontrakt, stosując własną logikę.
Pamiętaj: możesz rozszerzyć tylko jedną klasę, ale możesz implementować wiele interfejsów. Wybierz extends w przypadku rzeczywistych relacji dziedziczenia, a implements, gdy potrzebujesz elastyczności lub chcesz wymusić kontrakt bez współdzielenia szczegółów implementacji.
Wyzwanie
ŁatwyZbudujmy system pracowników, który pokazuje, kiedy używać extends, a kiedy implements. Utworzysz bazową klasę pracownika, a następnie pokażesz oba podejścia: jedną klasę, która naprawdę „jest” pracownikiem i dziedziczy zachowanie, oraz drugą, która po prostu „potrafi robić” to, co robi pracownik, ale stosuje całkowicie własną logikę.
Podzielisz kod na dwa pliki:
worker.dart: Zdefiniuj tutaj hierarchię pracowników:- Klasę
Workerz właściwościąString namei konstruktorem. Dodaj metodęwork(), która wyświetla[name] is working..., oraz metodętakeBreak(), która wyświetla[name] takes a coffee break - Klasę
OfficeWorker, która extendsWorker. Dodaj właściwośćString department. Zastąp metodęwork(), aby wyświetlała[name] is typing reports in [department], ale zachowaj odziedziczone zachowanie metodytakeBreak() - Klasę
RobotWorker, która implementsWorker. Dodaj właściwośćString model. Ponieważ roboty tak naprawdę nie są pracownikami, ale potrafią robić to, co robią pracownicy, przygotuj całkowicie własne implementacje:work()powinna wyświetlaćRobot [model] is assembling parts, atakeBreak()powinna wyświetlaćRobot [model] is recharging
- Klasę
main.dart: Zaimportuj plik z pracownikami i pokaż oba podejścia:- Utwórz
OfficeWorkero imieniu'Alice'w dziale'Marketing' - Utwórz
RobotWorkerz modelem'RX-7' - W przypadku pracownika biurowego wywołaj
work(), a następnietakeBreak() - Wyświetl pusty wiersz
- W przypadku pracownika-robota wywołaj
work(), a następnietakeBreak()
- Utwórz
Zwróć uwagę, że OfficeWorker automatycznie dziedziczy metodę takeBreak(), ponieważ rozszerza klasę Worker — naprawdę „jest” pracownikiem. Tymczasem RobotWorker musi samodzielnie zaimplementować wszystko, ponieważ implementuje jedynie interfejs — „potrafi robić” to, co robi pracownik, ale na swój własny, robotyczny sposób.
Oczekiwany wynik:
Alice is typing reports in Marketing
Alice takes a coffee break
Robot RX-7 is assembling parts
Robot RX-7 is rechargingSpróbuj swoich sił
import 'worker.dart';
void main() {
// TODO: Utwórz obiekt OfficeWorker o imieniu 'Alice' w dziale 'Marketing'
// TODO: Utwórz obiekt RobotWorker z modelem 'RX-7'
// TODO: Dla pracownika biurowego wywołaj work(), a następnie takeBreak()
// TODO: Wypisz pustą linię
// TODO: Dla pracownika robota wywołaj work(), a następnie takeBreak()
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP
Pliki zewnętrzneBiblioteki i importyWprowadzenie do OOPKlasy a obiektySłowo kluczowe thisMetodyZmienne instancjiPodstawy konstruktorówPowtórka – prosty kalkulator4Bezpieczeństwo wartości null
Wprowadzenie do bezpieczeństwa wartości nullTypy dopuszczające null i niedopuszczające nullOperatory ? i !Słowo kluczowe late a bezpieczeństwo wartości nullOperatory uwzględniające nullBezpieczeństwo wartości null w klasachPodsumowanie — system profili użytkowników7Klasy abstrakcyjne i interfejsy
Klasy abstrakcyjneMetody abstrakcyjneInterfejsy w DartInterfejsy niejawneImplementowanie a rozszerzanieWiele interfejsówPowtórka — kalkulator kształtów10Kolekcje i typy generyczne
Przegląd List, Set i MapKolekcje bezpieczne typowoKlasy generyczneMetody generyczneOgraniczenia typów generycznychIterable i IteratorPowtórka — generyczne przechowywanie danych13Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieMetody rozszerzająceKlasy wywoływalneKlasy zapieczętowane (Dart 3)Rekordy (Dart 3)Wzorce i dopasowywanie (3.0)Typy wyliczeniowe z metodami16Projekt: Zarządzanie biblioteką
Omówienie projektuKlasy książek i użytkowników2Konstruktory w Dart
Konstruktor domyślnyKonstruktory nazwaneListy inicjalizująceKonstruktory stałeKonstruktory fabryczneKonstruktory przekierowującePodsumowanie — budowanie kształtów5Hermetyzacja
Elementy publiczne a prywatneKonwencja prefiksu _Prywatność na poziomie bibliotekiGettery i settery — szczegółowoUkrywanie informacjiPodsumowanie — dane uczniów8Domieszki
Wprowadzenie do domieszekTworzenie domieszekKorzystanie z wielu domieszekSłowo kluczowe on w domieszkachDomieszka a dziedziczenieDomieszka a interfejsPodsumowanie – system zwierząt11Metody specjalne
Nadpisanie toString()Nadpisanie hashCode i ==Interfejs ComparableMetoda call()Nadpisanie noSuchMethodPodsumowanie — własna kolekcja14Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy3Właściwości klas
Elementy instancji a elementy statycznePola final i constZmienne inicjalizowane z opóźnieniemMetody i pola statyczneGettery i setteryPowtórzenie – menedżer kont bankowych6Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superPrzesłanianie metodAdnotacja @overrideSłowo kluczowe final dla klasKonstruktory i dziedziczeniePowtórzenie – hierarchia pracowników9Polimorfizm
Podstawy polimorfizmuPolimorfizm za pomocą interfejsówSprawdzanie typu w czasie działaniaOperatory is i asSłowo kluczowe covariantPodsumowanie — procesor płatnościPoćwicz samodzielnie: Kompilator Dart online