Menu
CoddyTech

이터레이터 패턴

Coddy Lua 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 70개 중 64번째.

객체 안에 저장된 항목 모음이 있을 때, 흔히 그 항목들을 반복해서 살펴보고 싶을 거예요. Lua의 일반 for 반복문은 어떤 반복자 함수와도 함께 사용할 수 있어요. 매 반복을 시작하기 전에 해당 함수를 호출하고, 함수가 nil을 반환하면 멈춰요.

이터레이터 패턴은 객체에 이러한 함수를 반환하는 메서드를 제공합니다. 이 함수는 위치를 지역 변수에 저장하므로, 위치는 컬렉션이 아니라 하나의 루프에 속합니다.

local Collection = {}
Collection.__index = Collection

function Collection:new()
    local obj = { items = {} }
    setmetatable(obj, Collection)
    return obj
end

function Collection:add(item)
    table.insert(self.items, item)
end

function Collection:iter()
    local index = 0
    return function()
        index = index + 1
        return self.items[index]
    end
end

bag:iter()를 호출할 때마다 자체 index를 가진 새 함수가 생성되며, index는 0에서 시작합니다. 이 함수는 클로저이므로 iter가 반환된 뒤에도 index와 self를 계속 사용할 수 있습니다. 마지막 항목을 지나면 self.items[index]는 nil이 되고 루프가 멈춥니다.

local bag = Collection:new()
bag:add("apple")
bag:add("banana")

for item in bag:iter() do
    print(item)  -- apple, 그다음 banana
end

for item in bag:iter() do
    print(item)  -- 다시 apple, 그다음 banana
end

위치는 컬렉션 자체에 저장하지 마세요. 객체가 self.index를 저장하고 자체 반복자 역할을 한다면, 첫 번째 루프가 끝났을 때 인덱스가 마지막 위치에 남으므로 두 번째 루프에서는 아무것도 출력되지 않습니다. 또한 break로 일찍 멈춘 루프가 있으면 다음 루프는 중간부터 시작하게 됩니다.

challenge icon

챌린지

쉬움

Lua의 일반 for 루프로 순회할 수 있는 Playlist 클래스를 만들어 봅시다! 이터레이터 함수를 반환하는 :iter() 메서드로 Iterator 패턴을 구현하게 됩니다.

두 개의 파일에 코드를 작성합니다.

  • Playlist.lua: 노래를 내부에 저장하는 Playlist 클래스를 만듭니다. 클래스에는 비어 있는 노래 목록을 초기화하는 :new() 생성자와 노래를 목록에 추가하는 :addSong(title) 메서드가 필요합니다. 무엇보다도 호출될 때마다 새 함수를 반환하는 :iter() 메서드를 추가하세요. 이 함수는 지역 변수에 현재 위치를 저장하고, 호출될 때마다 다음 노래를 반환합니다. 더 이상 노래가 없으면 nil을 반환합니다.
  • main.lua: Playlist 모듈을 불러와 새 플레이리스트를 만듭니다. 입력으로 받은 노래를 플레이리스트에 추가한 다음, playlist:iter()를 사용하는 일반 for 루프로 각 노래 제목을 한 줄씩 출력합니다.

:iter()를 호출할 때마다 첫 번째 노래부터 시작하므로, 같은 플레이리스트를 원하는 횟수만큼 반복해서 순회할 수 있습니다.

플레이리스트에 추가할 노래 제목을 나타내는 입력을 세 개 받습니다. 입력 순서대로 추가하면 됩니다.

예를 들어 입력이 Bohemian Rhapsody, Stairway to Heaven, Hotel California라면 출력은 다음과 같아야 합니다.

Bohemian Rhapsody
Stairway to Heaven
Hotel California

입력이 Yesterday, Imagine, Let It Be라면 출력은 다음과 같아야 합니다.

Yesterday
Imagine
Let It Be

직접 해보기

-- Playlist 모듈을 불러옵니다
local Playlist = require('Playlist')

-- 입력에서 노래 제목 3개를 읽습니다
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()

-- TODO: Playlist:new()를 사용해 새 재생목록을 만듭니다

-- TODO: :addSong()을 사용해 노래 3개를 재생목록에 추가합니다

-- TODO: playlist:iter()에 대해 범용 for 루프를 사용합니다
-- 그리고 각 노래 제목을 한 줄에 하나씩 출력합니다
-- 힌트: for song in playlist:iter() do ... end
quiz icon실력 점검

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

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

직접 연습해 보세요: 온라인 Lua 컴파일러