Itérateurs personnalisés
Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 33 sur 65.
Python permet à une classe de se comporter comme une liste grâce à des méthodes magiques telles que __len__, __getitem__, __contains__ et __iter__. Godot dispose de méthodes virtuelles pour une seule de ces tâches : la boucle for. Trois méthodes permettent à for item in my_object: de fonctionner :
_iter_init(iter)s’exécute une fois, avant le premier tour. Elle définit la position de départ et renvoietrues’il existe un premier élément._iter_get(position)renvoie l’élément à la position actuelle, et la variable de boucle reçoit cette valeur._iter_next(iter)s’exécute avant chaque tour suivant. Elle passe à la position suivante et renvoiefalselorsqu’il n’y a plus d’éléments, ce qui termine la boucle.
# 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 est un tableau avec un emplacement que Godot crée pour chaque boucle. iter[0] contient la position de cette boucle, et Godot transmet sa valeur à _iter_get(). Un Team fonctionne désormais dans une boucle for :
var team := Team.new()
team.add("Ada")
team.add("Bo")
for member in team:
print(member) # Ada, puis BoConservez la position dans iter[0], et non dans une variable membre telle que _position. Chaque boucle possède son propre iter, donc deux boucles sur la même équipe, même si l’une est imbriquée dans l’autre, ne se perturbent pas. Avec une variable membre, la boucle interne déplacerait la position de la boucle externe.
Les autres opérations sur une liste n’ont pas de méthode virtuelle : len(team) et team[0] sont des erreurs. Écris des méthodes ordinaires portant des noms comme celles d’Array, telles que size(), get_at(index) et has(member). Ne teste pas l’appartenance avec in : "Ada" in team vérifie si Team possède une propriété ou une méthode nommée Ada, donc le résultat est false.
Défi
FacileÉcrivez la classe Bookshelf dans bookshelf.gd. Elle conserve les titres dans _titles et peut contenir au maximum _capacity livres :
add(title)ajoute le titre et renvoietrue, ou renvoiefalsesans l’ajouter lorsque l’étagère est pleine ou contient déjà ce titre.size()renvoie le nombre de livres, ethas(title)indique si le titre se trouve sur l’étagère.get_at(index)renvoie le titre à cet index, ou une chaîne vide lorsque l’index est en dehors de l’étagère._iter_init(),_iter_next()et_iter_get()permettent à une boucleforde parcourir les titres dans l’ordre où ils ont été ajoutés.
Le code fourni lit la capacité, le nombre de titres et un titre par ligne, puis signale les titres qu’il n’a pas pu ajouter. Il affiche le nombre de livres, les énumère avec une boucle for sur l’étagère, puis lit un titre supplémentaire et indique si l’étagère le contient, ainsi que le dernier livre. Pour une capacité de 3, les titres Dune, Emma, Dune, Ulysses, Hamlet et la recherche Emma, le programme affiche :
Could not add: Dune
Could not add: Hamlet
Books: 3
1. Dune
2. Emma
3. Ulysses
Has Emma: true
Last: UlyssesVotre code doit être placé dans bookshelf.gd. main.gd contient le code d’entrée/sortie fourni et ne peut pas être modifié.
Essayez vous-même
extends Node
func _ready():
# Code d'entrée/sortie fourni : laissez-le tel quel
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))
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses et objetsLe mot-clé selfMéthodesPropriétésConstructeur (_init)Récapitulatif - Calculatrice simple4Polymorphisme
Retour sur la redéfinition des méthodesTypage canardClasses et méthodes abstraitesConception d’interfacesRécapitulatif – Calculateur de formes7Signaux
Qu’est-ce qu’un signal ?Déclarer et émettreSe connecter aux signauxSignaux avec argumentsRécapitulatif - système de santé10Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron Composite2Propriétés de classe
Variables d’instance et variables statiquesFonctions statiquesSetters de propriétésGetters de propriétésPrivé par conventionRécapitulatif - Gestionnaire de comptes bancaires5Encapsulation
Membres publics et privésValidation avec les méthodes setterMasquage de l’informationPropriétés en lecture seuleRécapitulatif - Système de dossiers étudiants8Concepts avancés de la POO
Composition ou héritageClasses internesLes nœuds comme composantsRefCounted ou NodeEnums dans les classes3Héritage
Héritage de baseLe mot-clé superRedéfinition de méthodesChaînes d’héritageVérifier les types avec isRécapitulatif – Hiérarchie des employés6Méthodes spéciales
Introduction aux méthodes virtuellesLa méthode _to_stringItérateurs personnalisésRécapitulatif – Liste personnalisée9Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron StrategyEntraînez-vous par vous-même : Compilateur GDScript en ligne