Menu
CoddyTech

Iteradores personalizados

Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 33 de 65.

Python faz uma classe se comportar como uma lista com métodos mágicos como __len__, __getitem__, __contains__ e __iter__. Godot tem métodos virtuais para apenas uma dessas tarefas: o loop for. Três métodos fazem for item in my_object: funcionar:

  • _iter_init(iter) é executado uma vez, antes da primeira iteração. Ele define a posição inicial e retorna true se houver um primeiro elemento.
  • _iter_get(position) retorna o elemento na posição atual, e a variável do loop recebe esse valor.
  • _iter_next(iter) é executado antes de cada iteração seguinte. Ele avança para a próxima posição e retorna false quando não há mais elementos, encerrando o loop.
# 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 é um Array com uma posição que o Godot cria para cada loop. iter[0] contém a posição desse loop, e o Godot passa seu valor para _iter_get(). Agora, um Team funciona em um loop for:

var team := Team.new()
team.add("Ada")
team.add("Bo")
for member in team:
	print(member) # Ada, depois Bo

Mantenha a posição em iter[0], não em uma variável membro como _position. Cada loop tem seu próprio iter, então dois loops sobre o mesmo time, mesmo que um esteja dentro do outro, não interferem um no outro. Com uma variável membro, o loop interno moveria a posição do loop externo.

As outras operações de lista não têm método virtual: len(team) e team[0] são erros. Escreva métodos comuns com nomes como os de Array, por exemplo, size(), get_at(index) e has(member). Não teste a pertinência com in: "Ada" in team verifica se Team tem uma propriedade ou método chamado Ada, portanto o resultado é false.

challenge icon

Desafio

Fácil

Escreva a classe Bookshelf em bookshelf.gd. Ela mantém os títulos em _titles e comporta no máximo _capacity livros:

  • add(title) adiciona o título e retorna true, ou retorna false sem adicionar quando a estante está cheia ou já contém esse título.
  • size() retorna o número de livros, e has(title) informa se o título está na estante.
  • get_at(index) retorna o título nesse índice ou uma string vazia quando o índice está fora da estante.
  • _iter_init(), _iter_next() e _iter_get() permitem que um loop for percorra os títulos na ordem em que foram adicionados.

O código fornecido lê a capacidade, o número de títulos e um título por linha, e informa os títulos que não conseguiu adicionar. Ele imprime o número de livros, lista-os com um loop for pela estante, depois lê mais um título e imprime se a estante o contém e qual é o último livro. Para a capacidade 3, os títulos Dune, Emma, Dune, Ulysses, Hamlet e a busca Emma, ele imprime:

Could not add: Dune
Could not add: Hamlet
Books: 3
1. Dune
2. Emma
3. Ulysses
Has Emma: true
Last: Ulysses

Seu código deve ficar em bookshelf.gd. main.gd contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

extends Node

func _ready():
	# Código de entrada/saída fornecido: mantenha-o como está
	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))
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação orientada a objetos

Pratique por conta própria: Compilador de GDScript online