Wprowadzenie do domieszek
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 50 z 110.
Dowiedziałeś się, że Dart pozwala dziedziczyć tylko po jednej klasie i chociaż możesz implementować wiele interfejsów, cały kod musisz napisać samodzielnie. A co, jeśli chcesz współdzielić rzeczywisty kod implementacji między wieloma niepowiązanymi klasami? Właśnie do tego służą domieszki.
Miksin to sposób na ponowne wykorzystanie kodu w wielu hierarchiach klas. Możesz myśleć o nim jak o zestawie metod i właściwości, które możesz „domieszać” do dowolnej klasy, nadając jej nowe możliwości bez użycia dziedziczenia.
mixin Swimming {
void swim() {
print('Swimming through the water');
}
}
class Duck with Swimming {
void quack() {
print('Quack!');
}
}
class Fish with Swimming {
void blowBubbles() {
print('Blub blub');
}
}
void main() {
var duck = Duck();
duck.quack();
duck.swim(); // Z mixinu
var fish = Fish();
fish.swim(); // Ta sama implementacja, inna klasa
}Zwróć uwagę na słowo kluczowe with — w ten sposób stosujesz domieszkę do klasy. W przeciwieństwie do implements nie musisz samodzielnie pisać metody. Domieszka udostępnia właściwy kod, a Twoja klasa automatycznie zyskuje tę funkcjonalność.
Mixin rozwiązują rzeczywisty problem: Duck i Fish nie są powiązane przez dziedziczenie, a jednak oba potrzebują zachowania umożliwiającego pływanie. Dzięki mixinom piszesz kod raz i udostępniasz go wszędzie tam, gdzie jest potrzebny.
Wyzwanie
ŁatwyZbudujmy system instrumentów muzycznych, który pokazuje, jak mixiny pozwalają współdzielić zachowanie między niepowiązanymi klasami. Utworzysz mixin zapewniający funkcje strojenia, a następnie zastosujesz go do różnych instrumentów, które nie są ze sobą powiązane przez dziedziczenie.
Podzielisz swój kod na dwa pliki:
instruments.dart: Zdefiniuj tutaj swój mixin i klasy instrumentów:- Mixin
Tunablez metodątune(), która wyświetlaTuning the instrument..., oraz metodącheckTuning(), która wyświetlaTuning is perfect! - Klasa
Guitar, która używa mixinuTunable. Dodaj właściwośćString brandi konstruktor. Dodaj metodęstrum(), która wyświetla[brand] guitar strumming chords - Klasa
Piano, która również używa mixinuTunable. Dodaj właściwośćint keysi konstruktor. Dodaj metodęplay(), która wyświetlaPlaying [keys]-key piano
- Mixin
main.dart: Zaimportuj plik z instrumentami i pokaż, jak oba niepowiązane instrumenty zyskują możliwość strojenia dzięki temu samemu mixinowi:- Utwórz obiekt
Guitarz marką'Fender' - Utwórz obiekt
Pianoz88klawiszami - Dla gitary: wywołaj
tune(), następniestrum(), a potemcheckTuning() - Wyświetl pusty wiersz
- Dla pianina: wywołaj
tune(), następnieplay(), a potemcheckTuning()
- Utwórz obiekt
Zwróć uwagę, że Guitar i Piano to zupełnie różne instrumenty, które nie są powiązane dziedziczeniem, a mimo to oba zyskują dokładnie te same metody strojenia z mixinu Tunable. Kod strojenia piszesz raz, a obie klasy mogą z niego korzystać dzięki słowu kluczowemu with.
Oczekiwany wynik:
Tuning the instrument...
Fender guitar strumming chords
Tuning is perfect!
Tuning the instrument...
Playing 88-key piano
Tuning is perfect!Spróbuj swoich sił
import 'instruments.dart';
void main() {
// TODO: Utwórz Guitar marki 'Fender'
// TODO: Utwórz Piano z 88 klawiszami
// TODO: Dla gitary: wywołaj tune(), następnie strum(), a potem checkTuning()
// TODO: Wypisz pustą linię
// TODO: Dla pianina: wywołaj tune(), następnie play(), a potem checkTuning()
}
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