Menu
CoddyTech

Introduction aux méthodes virtuelles

Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 31 sur 65.

Python possède des méthodes magiques telles que __init__ et __str__, que le langage appelle pour vous. Dans Godot, leur équivalent est la méthode virtuelle : une méthode portant un nom fixe, commençant par un trait de soulignement, que vous définissez dans votre classe et que Godot appelle au bon moment. Vous en avez déjà utilisé deux :

  • _init() s’exécute lorsque new() crée l’objet, avec les arguments transmis à new().
  • _ready() s’exécute lorsqu’un nœud entre dans l’arbre de scène, là où main.gd commence.

D’autres sont _to_string(), appelé lorsqu’un objet est affiché, les méthodes d’itérateur qui permettent à une boucle for de parcourir un objet (dans les deux prochaines leçons), et _notification(), qui reçoit des événements du moteur. L’un d’eux, NOTIFICATION_PREDELETE, est envoyé juste avant la suppression de l’objet :

# 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") # Torche du hall allumée
torch = null # Torche du hall éteinte

Un objet RefCounted est supprimé dès qu’aucune variable ne le référence plus, donc torch = null envoie la notification immédiatement. La valeur par défaut dans _init() rend l’argument de new() facultatif : Torch.new() crée une torche appelée Torch.

Python utilise également des méthodes magiques pour les opérateurs, comme __add__ pour + et __eq__ pour ==. GDScript ne prend pas en charge la surcharge des opérateurs : potion_a + potion_b est une erreur. Écris plutôt une méthode :

# 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) renvoie une nouvelle potion et laisse les deux originales inchangées. == entre deux objets vérifie si les deux côtés sont le même objet, et non si leurs valeurs correspondent : Potion.new(5) == Potion.new(5) est false. Écris une méthode telle que equals(other) lorsque tu as besoin de comparer des valeurs.

challenge icon

Défi

Facile

Écris la classe Counter dans counter.gd :

  • _init(start = 0, step_size = 1) stocke la valeur de départ dans value et le pas dans step. Les valeurs par défaut figurent déjà dans la signature, donc Counter.new(), Counter.new(5) et Counter.new(5, 2) fonctionnent tous.
  • tick() ajoute step à value.
  • plus(other) remplace l’opérateur +, que GDScript ne permet pas de définir : il renvoie un nouveau Counter dont la valeur est la somme des deux valeurs et dont le pas est celui de ce compteur. Aucun des deux compteurs ne change.
  • equals(other) renvoie true lorsque les deux compteurs ont la même valeur.

Le code fourni lit deux lignes qui créent les compteurs a et b (une ligne vide, START ou START STEP), puis une ligne indiquant combien de fois incrémenter a et b. Il affiche les deux compteurs, leur somme, si leurs valeurs sont égales et si a == b. Pour les lignes 5, 2 3 et 3 1, il affiche :

a: 8 (step 1)
b: 5 (step 3)
a plus b: 13 (step 1)
same value: false
same object: false

Ton code doit être placé dans counter.gd. main.gd contient le code fourni pour les entrées et sorties et ne peut pas être modifié.

Essayez vous-même

extends Node

func _ready():
	# Code d’entrée/sortie fourni : conservez-le tel quel
	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]))
quiz iconTestez-vous

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

Entraînez-vous par vous-même : Compilateur GDScript en ligne