Domieszka a dziedziczenie
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 54 z 110.
Skoro już wiesz, jak działają miksy, wyjaśnijmy, kiedy używać ich zamiast dziedziczenia. Kluczowa różnica polega na relacji, którą wyrażają.
Dziedziczenie reprezentuje relację „jest”. Dog jest Animal. Podklasa jest wyspecjalizowaną wersją klasy nadrzędnej i możesz rozszerzyć tylko jedną klasę.
Mixin z kolei reprezentują relację typu „potrafi coś robić”. Dog potrafi pływać, ale pływanie nie definiuje psa.
// Dziedziczenie: Dog JEST Animal
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// Mixin: Dog POTRAFI pływać (ale umiejętność pływania go nie definiuje)
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}Używaj dziedziczenia, gdy klasy mają wspólną podstawową tożsamość i potrzebujesz konstruktorów w klasie nadrzędnej. Używaj mixinów, gdy chcesz dodać możliwości klasom, które nie mają wspólnego przodka.
| Cecha | Dziedziczenie | Miksyna |
|---|---|---|
| Relacja | jest rodzajem | może wykonywać |
| Ograniczenie | Tylko jeden rodzic | Wiele miksyn |
| Konstruktory | Dozwolone | Niedozwolone |
| Zastosowanie | Specjalizacja | Współdzielone zachowanie |
Najlepsze jest to, że możesz połączyć oba podejścia — rozszerzyć jedną klasę i dodać wiele możliwości, zapewniając klasom dokładnie te funkcje, których potrzebują.
Wyzwanie
ŁatwyZbudujmy system pracowników, który pokazuje, kiedy używać dziedziczenia, a kiedy miksinów. Utworzysz klasę bazową opisującą relację „jest czymś” oraz miksiny reprezentujące możliwości („potrafi coś zrobić”), a następnie połączysz je, aby pokazać, jak oba podejścia współdziałają.
Podzielisz kod na trzy pliki:
worker.dart: Zdefiniuj klasę bazową, która określa podstawową tożsamość wszystkich pracowników:- Klasa
Workerz właściwościamiString nameiString department. Dodaj konstruktor przyjmujący obie wartości. Dodaj metodęintroduce(), która wyświetla[name] works in [department]
- Klasa
skills.dart: Zdefiniuj miksiny reprezentujące możliwości, jakie mogą mieć pracownicy (relacje „potrafi coś zrobić”):- Miksin
CanCodez metodąwriteCode(), która wyświetlaWriting code... - Miksin
CanDesignz metodącreateDesign(), która wyświetlaCreating design... - Miksin
CanManagez metodąleadTeam(), która wyświetlaLeading the team...
- Miksin
main.dart: Zaimportuj oba pliki i utwórz wyspecjalizowane typy pracowników, łącząc dziedziczenie z miksinami:- Klasę
Developer, która dziedziczy poWorkeri używa miksinuCanCode - Klasę
TechLead, która dziedziczy poWorkeri używa miksinówCanCodeorazCanManage - Utwórz obiekt
Developero imieniu'Alice'z działu'Engineering' - Utwórz obiekt
TechLeado imieniu'Bob'z działu'Engineering' - Dla Alice: wywołaj
introduce(), a następniewriteCode() - Wyświetl pusty wiersz
- Dla Boba: wywołaj
introduce(), następniewriteCode(), a na końculeadTeam()
- Klasę
Zauważ, że zarówno Developer, jak i TechLead są pracownikami (dziedziczenie), ale potrafią robić różne rzeczy (miksiny). Klasa TechLead łączy wiele możliwości bez potrzeby stosowania wielokrotnego dziedziczenia.
Oczekiwany wynik:
Alice works in Engineering
Writing code...
Bob works in Engineering
Writing code...
Leading the team...Spróbuj swoich sił
import 'worker.dart';
import 'skills.dart';
// TODO: Utwórz klasę Developer, która dziedziczy po Worker i korzysta z miksinu CanCode
// TODO: Utwórz klasę TechLead, która dziedziczy po Worker i korzysta z miksinów CanCode oraz CanManage
void main() {
// TODO: Utwórz obiekt Developer o imieniu 'Alice' w dziale 'Engineering'
// TODO: Wywołaj introduce(), a następnie writeCode() dla Alice
// TODO: Wypisz pustą linię
// TODO: Utwórz obiekt TechLead o imieniu 'Bob' w dziale 'Engineering'
// TODO: Wywołaj introduce(), writeCode(), a następnie leadTeam() dla Bob
}
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