Menu
Coddy logo textTech

Iterable ve Iterator

Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 68 / 110.

Bir List, Set veya başka bir koleksiyon üzerinde her for-in döngüsü kullandığınızda, arka planda Iterable ve Iterator ile çalışıyorsunuz. Bu kavramları anlamak, üzerinde döngü kurulabilen kendi sınıflarınızı oluşturmanıza olanak tanır.

Bir Iterable, bir değer dizisi üretebilen herhangi bir nesnedir. Bir temel gereksinimi vardır: bir Iterator döndüren bir iterator alıcısı (getter). Iterator, öğeler arasında aslında tek tek ilerleyen şeydir:

var numbers = [1, 2, 3];
var iterator = numbers.iterator;

while (iterator.moveNext()) {
  print(iterator.current);  // 1, sonra 2, sonra 3
}

moveNext() yöntemi bir sonraki öğeye ilerler ve eğer bir öğe varsa true, bittiğinde ise false değerini döndürür. current özelliği size geçerli öğeyi verir.

Kendi sınıfınızı yinelenebilir hale getirmek için Iterable arayüzünü uygulayın:

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
  }
}

Şimdi Countdown, for-in döngüleri ve map, where ve fold gibi tüm Iterable metotlarıyla çalışır. Bu desen, Dart'ın koleksiyon ekosistemiyle sorunsuz bir şekilde entegre olan özel koleksiyonlar oluştururken temeldir.

challenge icon

Görev

Kolay

Bir for-in döngüsü kullanılarak üzerinde gezinilebilen özel bir aralık (range) oluşturucu inşa edelim! Belirli bir aralıktaki sayı dizisini oluşturmak için kendi Iterable ve Iterator sınıflarınızı oluşturacaksınız.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • range.dart: Bir sayı dizisi üretmek için birlikte çalışan iki sınıf oluşturun:
    • Iterator<int> arayüzünü uygulayan bir RangeIterator sınıfı. Bu sınıf mevcut konumu takip etmeli ve ne zaman duracağını bilmelidir. Yineleyici (iterator) ilk elemandan önce başlar, bu nedenle current değerine erişmeden önce moveNext() çağrılmalıdır.
    • Iterable<int> sınıfını genişleten bir Range sınıfı. Yapıcısında (constructor) bir start ve end değeri alır ve bir RangeIterator döndüren bir iterator alıcısı (getter) sağlar.
    Aralık, hem start hem de end değerlerini dahil etmelidir. Örneğin, Range(1, 5) şunları üretmelidir: 1, 2, 3, 4, 5.
  • main.dart: Range dosyanızı içe aktarın ve özel iterable yapınızı gösterin:
    • Bir Range(1, 5) oluşturun ve her sayıyı kendi satırına yazdırmak için bir for-in döngüsü kullanın
    • Boş bir satır yazdırın ('')
    • Bir Range(10, 13) oluşturun ve her değeri iki katına çıkarmak için map metodunu kullanın, ardından sonuç listesini yazdırın

Range sınıfınız Iterable sınıfını genişlettiği için, map, where ve fold gibi tüm güçlü koleksiyon metotlarına otomatik olarak erişim kazanır - Iterable arayüzünü uygulamanın güzelliği de budur!

Beklenen çıktı:

1
2
3
4
5

[20, 22, 24, 26]

Kopya kağıdı

Bir Iterable, bir değer dizisi üretebilen herhangi bir nesnedir. Bir Iterator döndüren bir iterator alıcısı (getter) gerektirir.

Bir Iterator, şunları kullanarak öğeler arasında tek tek ilerler:

  • moveNext() - bir sonraki öğeye ilerler ve eğer bir öğe varsa true, bittiğinde ise false döndürür
  • current - size mevcut öğeyi veren özelliktir

Bir iterator'ı manuel olarak kullanma:

var numbers = [1, 2, 3];
var iterator = numbers.iterator;

while (iterator.moveNext()) {
  print(iterator.current);  // 1, sonra 2, sonra 3
}

Özel bir sınıfı iterable yapmak için Iterable arayüzünü uygulayın ve ilgili bir Iterator sınıfı oluşturun:

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
  }
}

Iterable sınıfını genişleten sınıflar, for-in döngüleri ile çalışır ve map, where ve fold gibi tüm Iterable metotlarına otomatik olarak erişim kazanır.

Kendin dene

import 'range.dart';

void main() {
  // TODO: Bir Range(1, 5) oluşturun ve her sayıyı yazdırmak için bir for-in döngüsü kullanın
  
  
  // TODO: Boş bir satır yazdırın
  
  
  // TODO: Bir Range(10, 13) oluşturun, her değeri iki katına çıkarmak için map kullanın ve listeyi yazdırın
  
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler