사용자 정의 이터레이터
Coddy GDScript 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 65개 중 33번째.
Python은 __len__, __getitem__, __contains__, __iter__ 같은 매직 메서드를 사용해 클래스가 리스트처럼 동작하도록 합니다. Godot에는 이러한 작업 중 하나인 for 루프를 위한 가상 메서드만 있습니다. 다음 세 메서드로 for item in my_object:를 작동하게 할 수 있습니다.
_iter_init(iter)는 첫 번째 반복이 시작되기 전에 한 번 실행됩니다. 시작 위치를 설정하고 첫 번째 요소가 있으면true를 반환합니다._iter_get(position)는 현재 위치의 요소를 반환하며, 루프 변수는 그 값을 받습니다._iter_next(iter)는 다음 반복부터 각 반복 전에 실행됩니다. 다음 위치로 이동하고 더 이상 요소가 없으면false를 반환하여 루프를 종료합니다.
# team.gd
class_name Team
extends RefCounted
var _members: Array[String] = []
func add(member: String) -> void:
_members.append(member)
func _iter_init(iter: Array) -> bool:
iter[0] = 0
return iter[0] < _members.size()
func _iter_next(iter: Array) -> bool:
iter[0] += 1
return iter[0] < _members.size()
func _iter_get(position):
return _members[position]iter는 Godot이 각 반복문마다 생성하는 슬롯 하나가 있는 배열입니다. iter[0]에는 해당 반복문의 위치가 저장되며, Godot은 그 값을 _iter_get()에 전달합니다. 이제 Team은 for 반복문에서 작동합니다:
var team := Team.new()
team.add("Ada")
team.add("Bo")
for member in team:
print(member) # Ada, 그다음 Bo위치는 iter[0]에 저장하고, _position과 같은 멤버 변수에는 저장하지 마세요. 각 루프는 자체 iter를 가지므로, 같은 팀을 순회하는 두 루프가 서로 중첩되어 있더라도 서로 방해하지 않습니다. 멤버 변수를 사용하면 내부 루프가 외부 루프의 위치를 이동시키게 됩니다.
다른 리스트 작업에는 가상 메서드가 없습니다. len(team)과 team[0]은 오류를 발생시킵니다. size(), get_at(index), has(member)처럼 Array의 메서드와 비슷한 이름으로 일반 메서드를 작성하세요. in으로 멤버십을 확인하지 마세요. "Ada" in team은 Team에 Ada라는 이름의 속성이나 메서드가 있는지 확인하므로, 결과는 false입니다.
챌린지
쉬움bookshelf.gd에 Bookshelf 클래스를 작성하세요. 책 제목은 _titles에 저장하고, 책은 최대 _capacity권까지 보관합니다:
add(title)는 제목을 추가하고true를 반환합니다. 책장이 가득 찼거나 이미 해당 제목이 있으면 추가하지 않고false를 반환합니다.size()는 책의 수를 반환하고,has(title)는 해당 제목이 책장에 있는지 반환합니다.get_at(index)는 해당 인덱스의 제목을 반환하고, 인덱스가 책장의 범위를 벗어나면 빈 문자열을 반환합니다._iter_init(),_iter_next(),_iter_get()을 사용하면for루프에서 추가된 순서대로 제목을 순회할 수 있습니다.
제공된 코드는 보관 용량, 제목의 개수, 한 줄에 제목 하나씩을 읽고 추가할 수 없었던 제목을 출력합니다. 책의 수를 출력하고, 책장을 대상으로 하는 for 루프로 책 목록을 출력한 다음 제목을 하나 더 읽어 책장에 해당 제목이 있는지와 마지막 책을 출력합니다. 보관 용량이 3이고, 제목이 Dune, Emma, Dune, Ulysses, Hamlet이며 검색할 제목이 Emma일 때 출력 결과는 다음과 같습니다:
Could not add: Dune
Could not add: Hamlet
Books: 3
1. Dune
2. Emma
3. Ulysses
Has Emma: true
Last: Ulysses코드는 bookshelf.gd에 작성하세요. main.gd에는 제공된 입력/출력 코드가 있으며 수정할 수 없습니다.
직접 해보기
extends Node
func _ready():
# 제공된 입력/출력 코드: 그대로 유지하세요
var shelf := Bookshelf.new(int(OS.read_string_from_stdin()))
var count := int(OS.read_string_from_stdin())
for i in count:
var title := OS.read_string_from_stdin()
if not shelf.add(title):
print("Could not add: " + title)
print("Books: %d" % shelf.size())
var number := 1
for title in shelf:
print("%d. %s" % [number, title])
number += 1
var query := OS.read_string_from_stdin()
print("Has %s: %s" % [query, shelf.has(query)])
print("Last: " + shelf.get_at(shelf.size() - 1))
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 GDScript 컴파일러