Introduzione ai metodi virtuali
Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 31 di 65.
Python ha metodi magici come __init__ e __str__, che il linguaggio richiama per te. La versione di Godot è il metodo virtuale: un metodo con un nome fisso, che inizia con un trattino basso, che definisci nella tua classe e che Godot richiama al momento giusto. Ne hai già usati due:
_init()viene eseguito quandonew()crea l'oggetto, con gli argomenti forniti anew()._ready()viene eseguito quando un nodo entra nell'albero della scena, ovvero il punto da cui iniziamain.gd.
Altri sono _to_string(), chiamato quando viene stampato un oggetto, i metodi iteratore che permettono a un ciclo for di scorrere un oggetto (entrambi nelle prossime lezioni) e _notification(), che riceve eventi dal motore. Uno di questi, NOTIFICATION_PREDELETE, arriva subito prima che l'oggetto venga eliminato:
# torch.gd
class_name Torch
extends RefCounted
var label: String
func _init(new_label: String = "Torch") -> void:
label = new_label
print(label, " lit")
func _notification(what: int) -> void:
if what == NOTIFICATION_PREDELETE:
print(label, " burned out")# main.gd
var torch := Torch.new("Hall torch") # Torcia del corridoio accesa
torch = null # Torcia del corridoio esauritaUn oggetto RefCounted viene eliminato non appena nessuna variabile vi fa più riferimento, quindi torch = null invia subito la notifica. Il valore predefinito in _init() rende facoltativo l’argomento di new(): Torch.new() crea una torcia chiamata Torch.
Python usa anche metodi magici per gli operatori, come __add__ per + e __eq__ per ==. GDScript non supporta l’overloading degli operatori: potion_a + potion_b è un errore. Scrivi invece un metodo:
# potion.gd
class_name Potion
extends RefCounted
var power: int
func _init(start_power: int) -> void:
power = start_power
func combined(other: Potion) -> Potion:
return Potion.new(power + other.power)potion_a.combined(potion_b) restituisce una nuova pozione e lascia entrambe le originali invariate. == tra due oggetti verifica se entrambi i lati sono lo stesso oggetto, non se i loro valori corrispondono: Potion.new(5) == Potion.new(5) è false. Scrivi un metodo come equals(other) quando devi confrontare i valori.
Sfida
FacileScrivi la classe Counter in counter.gd:
_init(start = 0, step_size = 1)memorizza il valore iniziale invaluee l’ampiezza del passo instep. I valori predefiniti sono già nella firma, quindi funzionano tutte le chiamateCounter.new(),Counter.new(5)eCounter.new(5, 2).tick()aggiungestepavalue.plus(other)sostituisce l’operatore+, che GDScript non permette di definire: restituisce unCounternuovo il cui valore è la somma dei due valori e il cui passo è quello di questo contatore. Nessuno dei due contatori cambia.equals(other)restituiscetruequando entrambi i contatori hanno lo stesso valore.
Il codice fornito legge due righe che creano i contatori a e b (una riga vuota, START oppure START STEP), poi una riga con il numero di volte in cui eseguire il tick di a e b. Stampa entrambi i contatori, la loro somma, se i loro valori sono uguali e se a == b. Con le righe 5, 2 3 e 3 1 stampa:
a: 8 (step 1)
b: 5 (step 3)
a plus b: 13 (step 1)
same value: false
same object: falseIl tuo codice va inserito in counter.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 a := make_counter(OS.read_string_from_stdin())
var b := make_counter(OS.read_string_from_stdin())
var ticks := OS.read_string_from_stdin().split(" ")
for i in int(ticks[0]):
a.tick()
for i in int(ticks[1]):
b.tick()
print("a: %d (step %d)" % [a.value, a.step])
print("b: %d (step %d)" % [b.value, b.step])
var total := a.plus(b)
print("a plus b: %d (step %d)" % [total.value, total.step])
print("same value: %s" % a.equals(b))
print("same object: %s" % (a == b))
func make_counter(line: String) -> Counter:
var parts := line.split(" ", false)
if parts.is_empty():
return Counter.new()
if parts.size() == 1:
return Counter.new(int(parts[0]))
return Counter.new(int(parts[0]), int(parts[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