Menu
CoddyTech

Benutzerdefinierte Iteratoren

Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 33 von 65.

Python lässt eine Klasse sich mit magischen Methoden wie __len__, __getitem__, __contains__ und __iter__ wie eine Liste verhalten. Godot hat virtuelle Methoden nur für eine dieser Aufgaben: die for-Schleife. Drei Methoden sorgen dafür, dass for item in my_object: funktioniert:

  • _iter_init(iter) wird einmal vor dem ersten Durchlauf ausgeführt. Sie setzt die Startposition und gibt true zurück, wenn es ein erstes Element gibt.
  • _iter_get(position) gibt das Element an der aktuellen Position zurück, und die Schleifenvariable erhält diesen Wert.
  • _iter_next(iter) wird vor jedem weiteren Durchlauf ausgeführt. Sie geht zur nächsten Position und gibt false zurück, wenn es keine weiteren Elemente gibt, wodurch die Schleife beendet wird.
# 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 ist ein Array mit einem Slot, das Godot für jede Schleife erstellt. iter[0] enthält die Position dieser Schleife, und Godot übergibt seinen Wert an _iter_get(). Ein Team funktioniert jetzt in einer for-Schleife:

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

Speichere die Position in iter[0], nicht in einer Member-Variable wie _position. Jede Schleife erhält ihr eigenes iter, sodass zwei Schleifen über dasselbe Team einander nicht stören, selbst wenn eine innerhalb der anderen liegt. Mit einer Member-Variable würde die innere Schleife die Position der äußeren Schleife verändern.

Für die übrigen Listenaufgaben gibt es keine virtuelle Methode: len(team) und team[0] sind Fehler. Schreibe gewöhnliche Methoden mit Namen wie bei Array, etwa size(), get_at(index) und has(member). Prüfe die Mitgliedschaft nicht mit in: "Ada" in team prüft, ob Team eine Eigenschaft oder Methode namens Ada hat, also ist das Ergebnis false.

challenge icon

Aufgabe

Einfach

Schreibe die Klasse Bookshelf in bookshelf.gd. Sie speichert die Titel in _titles und fasst höchstens _capacity Bücher:

  • add(title) fügt den Titel hinzu und gibt true zurück oder gibt false zurück, ohne ihn hinzuzufügen, wenn das Regal voll ist oder den Titel bereits enthält.
  • size() gibt die Anzahl der Bücher zurück, und has(title), ob der Titel im Regal steht.
  • get_at(index) gibt den Titel an diesem Index zurück oder einen leeren String, wenn der Index außerhalb des Regals liegt.
  • _iter_init(), _iter_next() und _iter_get() ermöglichen einer for-Schleife, die Titel in der Reihenfolge durchzugehen, in der sie hinzugefügt wurden.

Der bereitgestellte Code liest die Kapazität, die Anzahl der Titel und jeweils einen Titel pro Zeile ein und gibt die Titel aus, die nicht hinzugefügt werden konnten. Er gibt die Anzahl der Bücher aus, listet sie mit einer for-Schleife über das Regal auf, liest dann einen weiteren Titel ein und gibt aus, ob das Regal ihn enthält, sowie das letzte Buch. Bei einer Kapazität von 3, den Titeln Dune, Emma, Dune, Ulysses, Hamlet und der Suche nach Emma gibt es Folgendes aus:

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

Dein Code gehört in bookshelf.gd. main.gd enthält den bereitgestellten Ein-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

extends Node

func _ready():
	# Vorgegebener Ein-/Ausgabecode: unverändert lassen
	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 dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-GDScript-Compiler