Klasy generyczne
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 65 z 110.
Wiesz już, jak wbudowane kolekcje Dart, takie jak List<String>, używają parametrów typów. Teraz czas utworzyć własne klasy generyczne, które działają z dowolnym określonym przez Ciebie typem.
Klasa generyczna używa parametru typu (zazwyczaj T) jako symbolu zastępczego dla rzeczywistego typu, który zostanie podany podczas tworzenia instancji:
class Box<T> {
T content;
Box(this.content);
T getContent() => content;
}
void main() {
var stringBox = Box<String>('Hello');
var intBox = Box<int>(42);
print(stringBox.getContent()); // Hello
print(intBox.getContent()); // 42
}T pełni rolę zmiennej typu — gdy tworzysz Box<String>, każde T w klasie staje się String. Dzięki temu masz bezpieczeństwo typów bez pisania osobnych klas dla każdego typu.
Możesz użyć wielu parametrów typu, gdy Twoja klasa musi działać z więcej niż jednym typem:
class Pair<K, V> {
K first;
V second;
Pair(this.first, this.second);
}
void main() {
var pair = Pair<String, int>('age', 25);
print('${pair.first}: ${pair.second}'); // age: 25
}Klasy generyczne stanowią podstawę wielokrotnego użytku i bezpiecznego typowo kodu. Zamiast powielać logikę dla różnych typów lub tracić informacje o typie za pomocą dynamic, generyki pozwalają pisać elastyczny kod, który kompilator nadal może weryfikować.
Wyzwanie
ŁatwyZbudujmy system pakowania prezentów, który wykorzystuje klasy generyczne do tworzenia elastycznych pojemników na różne typy elementów. Utworzysz generyczną klasę Wrapper, która może opakować dowolny typ zawartości, oraz klasę GiftBox z dwoma parametrami typu, aby połączyć prezent z wiadomością na kartce.
Podzielisz swój kod na dwa pliki:
wrapper.dart: Zdefiniuj tutaj swoje klasy generyczne:- Generyczna klasa
Wrapper<T>z właściwościąT contenti konstruktorem. Dodaj metodęunwrap(), która zwraca zawartość, oraz metodędescribe(), która wypisujeWrapped: [content] - Generyczna klasa
GiftBox<G, C>z dwiema właściwościami:G giftiC card. Dodaj konstruktor i metodęopen(), która wypisujeGift: [gift]w jednym wierszu, aCard: [card]w następnym wierszu
- Generyczna klasa
main.dart: Zaimportuj plik wrapper i zademonstruj działanie klas generycznych z różnymi typami:- Utwórz obiekt
Wrapper<String>zawierający'Chocolate'i wywołajdescribe() - Utwórz obiekt
Wrapper<int>zawierający42i wywołajdescribe() - Utwórz obiekt
Wrapper<double>zawierający3.14i wywołajdescribe() - Wypisz pusty wiersz
- Utwórz obiekt
GiftBox<String, String>z prezentem'Teddy Bear'i kartką'Happy Birthday!', a następnie wywołajopen() - Wypisz pusty wiersz
- Utwórz obiekt
GiftBox<int, String>z prezentem100(oznaczającym kwotę na karcie podarunkowej) i kartką'Congratulations!', a następnie wywołajopen()
- Utwórz obiekt
Zwróć uwagę, że ta sama klasa Wrapper bez problemu działa z łańcuchami znaków, liczbami całkowitymi i liczbami zmiennoprzecinkowymi. Klasa GiftBox pokazuje, jak używać dwóch parametrów typu do łączenia różnych typów — prezent może być dowolnego typu, a wiadomość na kartce pozostaje łańcuchem znaków.
Oczekiwany wynik:
Wrapped: Chocolate
Wrapped: 42
Wrapped: 3.14
Gift: Teddy Bear
Card: Happy Birthday!
Gift: 100
Card: Congratulations!Spróbuj swoich sił
import 'wrapper.dart';
void main() {
// TODO: Utwórz Wrapper<String> zawierający 'Chocolate' i wywołaj describe()
// TODO: Utwórz Wrapper<int> zawierający 42 i wywołaj describe()
// TODO: Utwórz Wrapper<double> zawierający 3.14 i wywołaj describe()
// TODO: Wypisz pusty wiersz
// TODO: Utwórz GiftBox<String, String> z prezentem 'Teddy Bear'
// i kartką 'Happy Birthday!', a następnie wywołaj open()
// TODO: Wypisz pusty wiersz
// TODO: Utwórz GiftBox<int, String> z prezentem 100
// i kartką 'Congratulations!', a następnie wywołaj open()
}
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