Iterable i Iterator
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 68 z 110.
Za każdym razem, gdy używasz pętli for-in na liście, zbiorze lub innej kolekcji, pod spodem korzystasz z Iterable i Iterator. Zrozumienie tych pojęć pozwala tworzyć własne klasy, po których można iterować.
Obiekt Iterable to dowolny obiekt, który może wygenerować sekwencję wartości. Ma jeden kluczowy wymóg: getter iterator, który zwraca obiekt Iterator. To Iterator faktycznie przechodzi przez elementy jeden po drugim:
var numbers = [1, 2, 3];
var iterator = numbers.iterator;
while (iterator.moveNext()) {
print(iterator.current); // 1, potem 2, potem 3
}Metoda moveNext() przechodzi do następnego elementu i zwraca true, jeśli taki istnieje, albo false, gdy iterowanie się zakończy. Właściwość current zwraca bieżący element.
Aby Twoja własna klasa była iterowalna, zaimplementuj interfejs Iterable:
class Countdown extends Iterable<int> {
final int start;
Countdown(this.start);
@override
Iterator<int> get iterator => CountdownIterator(start);
}
class CountdownIterator implements Iterator<int> {
int _current;
CountdownIterator(int start) : _current = start + 1;
@override
int get current => _current;
@override
bool moveNext() {
if (_current > 0) {
_current--;
return true;
}
return false;
}
}
void main() {
for (var n in Countdown(3)) {
print(n); // 3, 2, 1, 0
}
}Teraz Countdown działa z pętlami for-in i wszystkimi metodami Iterable, takimi jak map, where i fold. Ten wzorzec jest niezbędny podczas tworzenia niestandardowych kolekcji, które bezproblemowo integrują się z ekosystemem kolekcji Dart.
Wyzwanie
ŁatwyStwórzmy własny generator zakresu, po którym można iterować za pomocą pętli for-in! Utworzysz własne klasy Iterable i Iterator, aby generować ciąg liczb z określonego zakresu.
Podzielisz kod na dwa pliki:
range.dart: Utwórz dwie współpracujące ze sobą klasy, które generują ciąg liczb:- Klasa
RangeIterator, która implementujeIterator<int>. Powinna śledzić bieżącą pozycję i wiedzieć, kiedy się zatrzymać. Iterator zaczyna przed pierwszym elementem, więc przed uzyskaniem dostępu docurrenttrzeba wywołaćmoveNext(). - Klasa
Range, która rozszerzaIterable<int>. Przyjmuje wartościstartiendw konstruktorze oraz udostępnia getteriterator, który zwracaRangeIterator.
start, jak iend. Na przykładRange(1, 5)powinien generować: 1, 2, 3, 4, 5.- Klasa
main.dart: Zaimportuj plik z zakresem i zademonstruj własną iterowalną kolekcję:- Utwórz
Range(1, 5)i użyj pętlifor-in, aby wypisać każdą liczbę w osobnym wierszu - Wypisz pusty wiersz
- Utwórz
Range(10, 13), użyj metodymap, aby podwoić każdą wartość, a następnie wypisz wynikową listę
- Utwórz
Ponieważ klasa Range rozszerza Iterable, automatycznie zyskuje dostęp do wszystkich przydatnych metod kolekcji, takich jak map, where i fold — na tym polega piękno implementowania interfejsu Iterable!
Oczekiwany wynik:
1
2
3
4
5
[20, 22, 24, 26]Spróbuj swoich sił
import 'range.dart';
void main() {
// TODO: Utwórz Range(1, 5) i użyj pętli for-in, aby wypisać każdą liczbę
// TODO: Wypisz pustą linię
// TODO: Utwórz Range(10, 13), użyj map, aby podwoić każdą wartość, i wypisz listę
}
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