이터레이터 패턴
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
endbag: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로 일찍 멈춘 루프가 있으면 다음 루프는 중간부터 시작하게 됩니다.
챌린지
쉬움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
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 Lua 컴파일러