Iteratori personalizzati
Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 33 di 65.
Python permette a una classe di comportarsi come una lista grazie a metodi magici come __len__, __getitem__, __contains__ e __iter__. Godot ha metodi virtuali per uno solo di questi compiti: il ciclo for. Tre metodi permettono di usare for item in my_object::
_iter_init(iter)viene eseguito una volta, prima del primo giro. Imposta la posizione iniziale e restituiscetruese esiste un primo elemento._iter_get(position)restituisce l'elemento nella posizione corrente e la variabile del ciclo riceve quel valore._iter_next(iter)viene eseguito prima di ogni giro successivo. Passa alla posizione seguente e restituiscefalsequando non ci sono altri elementi, terminando così il ciclo.
# 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 è un array con uno slot che Godot crea per ogni ciclo. iter[0] contiene la posizione di quel ciclo e Godot passa il suo valore a _iter_get(). Ora un Team funziona in un ciclo for:
var team := Team.new()
team.add("Ada")
team.add("Bo")
for member in team:
print(member) # Ada, poi BoMantieni la posizione in iter[0], non in una variabile membro come _position. Ogni ciclo ha il proprio iter, quindi due cicli sulla stessa squadra, anche uno dentro l’altro, non si intralciano. Con una variabile membro, il ciclo interno sposterebbe la posizione del ciclo esterno.
Gli altri metodi delle liste non hanno un metodo virtuale: len(team) e team[0] generano errori. Scrivi metodi ordinari con nomi simili a quelli di Array, come size(), get_at(index) e has(member). Non verificare l'appartenenza con in: "Ada" in team verifica se Team ha una proprietà o un metodo chiamato Ada, quindi il risultato è false.
Sfida
FacileScrivi la classe Bookshelf in bookshelf.gd. Mantiene i titoli in _titles e contiene al massimo _capacity libri:
add(title)aggiunge il titolo e restituiscetrue, oppure restituiscefalsesenza aggiungerlo se lo scaffale è pieno o contiene già quel titolo.size()restituisce il numero di libri ehas(title)indica se il titolo è sullo scaffale.get_at(index)restituisce il titolo in quell'indice, oppure una stringa vuota se l'indice è fuori dallo scaffale._iter_init(),_iter_next()e_iter_get()consentono a un ciclofordi scorrere i titoli nell'ordine in cui sono stati aggiunti.
Il codice fornito legge la capacità, il numero di titoli e un titolo per riga, e segnala i titoli che non è riuscito ad aggiungere. Stampa il numero di libri, li elenca con un ciclo for sullo scaffale, poi legge un altro titolo e stampa se lo scaffale lo contiene e qual è l'ultimo libro. Per una capacità di 3, i titoli Dune, Emma, Dune, Ulysses, Hamlet e la ricerca Emma, stampa:
Could not add: Dune
Could not add: Hamlet
Books: 3
1. Dune
2. Emma
3. Ulysses
Has Emma: true
Last: UlyssesInserisci il tuo codice in bookshelf.gd. main.gd contiene il codice fornito per l'input/output e non può essere modificato.
Provalo tu
extends Node
func _ready():
# Codice di input/output fornito: lascialo così com'è
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))
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniIntroduzione alla programmazione orientata agli oggettiClassi e oggetti a confrontoLa parola chiave selfMetodiProprietàCostruttore (_init)Riepilogo - Calcolatrice semplice4Polimorfismo
Ripasso dell'override dei metodiDuck typingClassi e metodi astrattiProgettazione delle interfacceRiepilogo - Calcolatore di forme7Segnali
Che cos'è un segnale?Dichiarare ed emettereCollegarsi ai segnaliSegnali con argomentiRipasso - Sistema della salute10Pattern di progettazione, parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern Composite2Proprietà delle classi
Variabili di istanza e staticheFunzioni staticheSetter delle proprietàGetter delle proprietàPrivato per convenzioneRiepilogo - Gestore di conti bancari5Incapsulamento
Membri pubblici e privatiValidazione con i setterNascondimento delle informazioniProprietà di sola letturaRiepilogo - Sistema di gestione dei dati degli studenti8Concetti avanzati di OOP
Composizione vs ereditarietàClassi interneNodi come componentiRefCounted vs NodeEnum nelle classi11Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente3Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiCatene di ereditarietàControlli di tipo con isRipasso - Gerarchia dei dipendenti6Metodi speciali
Introduzione ai metodi virtualiIl metodo _to_stringIteratori personalizzatiRiepilogo - Lista personalizzata9Modelli di progettazione, parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern ObserverPattern StrategyEsercitati da solo: Compilatore GDScript online