Menu
Coddy logo textTech

Iterable과 Iterator

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 68번째.

List, Set 또는 다른 컬렉션에서 for-in 루프를 사용할 때마다, 여러분은 내부적으로 IterableIterator를 사용하고 있는 것입니다. 이러한 개념을 이해하면 반복 가능한 자신만의 클래스를 만들 수 있습니다.

Iterable은 일련의 값을 생성할 수 있는 모든 객체입니다. 여기에는 한 가지 핵심 요구 사항이 있습니다. 바로 Iterator를 반환하는 iterator 게터(getter)입니다. Iterator는 실제로 요소를 하나씩 훑으며 이동하는 역할을 합니다:

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

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

moveNext() 메서드는 다음 요소로 이동하며, 요소가 있으면 true를 반환하고 완료되면 false를 반환합니다. current 속성은 현재 요소를 제공합니다.

자신만의 클래스를 반복 가능하게 만들려면 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
  }
}

이제 Countdownfor-in 루프 및 map, where, fold와 같은 모든 Iterable 메서드와 함께 작동합니다. 이 패턴은 Dart의 컬렉션 생태계와 원활하게 통합되는 커스텀 컬렉션을 구축할 때 필수적입니다.

challenge icon

챌린지

쉬움

for-in 루프를 사용하여 반복할 수 있는 커스텀 범위 생성기를 만들어 봅시다! 지정된 범위 내의 숫자 시퀀스를 생성하기 위해 직접 IterableIterator 클래스를 만들게 됩니다.

코드를 두 개의 파일로 구성합니다:

  • range.dart: 숫자 시퀀스를 생성하기 위해 함께 작동하는 두 개의 클래스를 만듭니다:
    • Iterator<int>를 구현하는 RangeIterator 클래스. 이 클래스는 현재 위치를 추적하고 언제 멈춰야 할지 알아야 합니다. 반복자(iterator)는 첫 번째 요소 이전에서 시작하므로, current에 접근하기 전에 moveNext()가 호출되어야 합니다.
    • Iterable<int>를 상속받는 Range 클래스. 생성자에서 startend 값을 받으며, RangeIterator를 반환하는 iterator 게터(getter)를 제공합니다.
    범위는 startend를 모두 포함해야 합니다. 예를 들어, Range(1, 5)는 1, 2, 3, 4, 5를 생성해야 합니다.
  • main.dart: range 파일을 임포트하고 커스텀 iterable을 시연합니다:
    • Range(1, 5)를 생성하고 for-in 루프를 사용하여 각 숫자를 개별 줄에 출력합니다.
    • 빈 줄을 하나 출력합니다 ('').
    • Range(10, 13)을 생성하고 map 메서드를 사용하여 각 값을 두 배로 만든 다음, 결과 리스트를 출력합니다.

Range 클래스가 Iterable을 상속받기 때문에, map, where, fold와 같은 강력한 컬렉션 메서드들을 자동으로 사용할 수 있게 됩니다. 이것이 바로 Iterable 인터페이스를 구현하는 것의 장점입니다!

예상 출력:

1
2
3
4
5

[20, 22, 24, 26]

치트 시트

Iterable은 일련의 값을 생성할 수 있는 모든 객체를 의미합니다. 이는 Iterator를 반환하는 iterator 게터(getter)를 필요로 합니다.

Iterator는 다음을 사용하여 요소를 하나씩 이동합니다:

  • moveNext() - 다음 요소로 이동하며, 요소가 있으면 true를, 끝에 도달하면 false를 반환합니다.
  • current - 현재 요소를 제공하는 속성입니다.

반복자(iterator)를 수동으로 사용하기:

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

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

사용자 정의 클래스를 반복 가능하게 만들려면, Iterable 인터페이스를 구현하고 그에 대응하는 Iterator 클래스를 생성하세요:

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을 확장하는 클래스는 for-in 루프와 함께 작동하며 map, where, fold와 같은 모든 Iterable 메서드에 자동으로 접근할 수 있게 됩니다.

직접 해보기

import 'range.dart';

void main() {
  // TODO: Range(1, 5)를 생성하고 for-in 루프를 사용하여 각 숫자를 출력하세요
  
  
  // TODO: 빈 줄을 출력하세요
  
  
  // TODO: Range(10, 13)을 생성하고, map을 사용하여 각 값을 두 배로 만든 후 리스트를 출력하세요
  
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨