Podstawy polimorfizmu
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 57 z 110.
Polimorfizm oznacza „wiele form” — to możliwość traktowania obiektów różnych klas za pomocą wspólnego interfejsu. Odwołanie do klasy nadrzędnej może wskazywać na obiekt dowolnej klasy potomnej, a wywołana zostaje właściwa metoda, zależnie od rzeczywistego typu obiektu.
To jest potężne, ponieważ możesz napisać kod działający z typem nadrzędnym, a jednocześnie automatycznie poprawnie obsługujący wszystkie typy podrzędne:
class Animal {
void speak() => print('Some sound');
}
class Dog extends Animal {
@override
void speak() => print('Woof!');
}
class Cat extends Animal {
@override
void speak() => print('Meow!');
}
void main() {
Animal myPet = Dog(); // Typ rodzica, obiekt klasy potomnej
myPet.speak(); // Wynik: Woof!
myPet = Cat(); // Ta sama zmienna, inny obiekt
myPet.speak(); // Wynik: Meow!
}Zmienna myPet jest zadeklarowana jako Animal, ale przechowuje obiekt typu Dog lub Cat. Gdy wywoływana jest metoda speak(), Dart sprawdza rzeczywisty typ obiektu w czasie wykonywania i wywołuje odpowiednią nadpisaną metodę.
Pozwala ci to pisać elastyczne funkcje, które działają z dowolną podklasą:
void makeAllSpeak(List<Animal> animals) {
for (var animal in animals) {
animal.speak(); // Każde zwierzę odzywa się na swój sposób
}
}
void main() {
var pets = [Dog(), Cat(), Dog()];
makeAllSpeak(pets);
// Wynik: Woof! Meow! Woof!
}Funkcja nie musi wiedzieć o Dog ani Cat — działa po prostu z Animal. Dzięki temu Twój kod jest bardziej rozszerzalny, ponieważ dodawanie nowych typów zwierząt nie wymaga zmian w istniejących funkcjach.
Wyzwanie
ŁatwyZbudujmy system instrumentów muzycznych, który pokaże polimorfizm w praktyce. Utworzysz bazową klasę Instrument i kilka typów instrumentów, a następnie napiszesz funkcję, która pozwoli dowolnemu zestawowi instrumentów grać razem — bez znajomości ich konkretnych typów.
Podzielisz swój kod na dwa pliki:
instruments.dart: Zdefiniuj tutaj hierarchię instrumentów:- Klasę
Instrumentz właściwościąString namei konstruktorem. Dodaj metodęplay(), która wypisuje[name] makes a sound - Klasę
Guitar, która rozszerza klasęInstrumenti nadpisuje metodęplay(), aby wypisywała[name] strums melodically - Klasę
Drum, która rozszerza klasęInstrumenti nadpisuje metodęplay(), aby wypisywała[name] beats rhythmically - Klasę
Piano, która rozszerza klasęInstrumenti nadpisuje metodęplay(), aby wypisywała[name] plays harmoniously
performConcert(List<Instrument> instruments), która wypisujeConcert begins!, następnie przechodzi przez listę, wywołującplay()dla każdego instrumentu, a na końcu wypisujeConcert ends!- Klasę
main.dart: Zaimportuj plik z instrumentami i pokaż polimorfizm, tworząc zespół złożony z różnych instrumentów:- Utwórz listę typu
List<Instrument>, zawierającąGuitaro nazwie'Acoustic',Drumo nazwie'Snare'orazPianoo nazwie'Grand' - Przekaż tę listę do funkcji
performConcert()
- Utwórz listę typu
Zwróć uwagę, że funkcja performConcert() działa z typem nadrzędnym Instrument, a mimo to każdy instrument gra na swój wyjątkowy sposób. To właśnie polimorfizm — to samo wywołanie metody daje różne zachowanie w zależności od rzeczywistego typu obiektu.
Oczekiwany wynik:
Concert begins!
Acoustic strums melodically
Snare beats rhythmically
Grand plays harmoniously
Concert ends!Spróbuj swoich sił
import 'instruments.dart';
void main() {
// TODO: Utwórz List<Instrument> zawierającą:
// - Guitar o nazwie 'Acoustic'
// - Drum o nazwie 'Snare'
// - Piano o nazwie 'Grand'
// TODO: Wywołaj performConcert() ze swoją listą instrumentów
}
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