Menu
CoddyTech

Typage canard

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

Le typage canard s’intéresse à ce qu’un objet peut faire, et non à la classe à laquelle il appartient. S’il possède la méthode que vous appelez, l’appel fonctionne. Le nom vient du dicton « s’il nage comme un canard et cancane comme un canard, c’est un canard ».

Ces deux classes n’ont pas de parent commun, mais elles possèdent toutes deux swim() et quack() :

# duck.gd
class_name Duck
extends RefCounted

func swim() -> String:
	return "Duck swimming"

func quack() -> String:
	return "Quack!"
# robot.gd
class_name Robot
extends RefCounted

func swim() -> String:
	return "Robot swimming with propellers"

func quack() -> String:
	return "Robot sound: BEEP BEEP!"

Un paramètre sans type accepte n’importe quel objet. La fonction appelle les méthodes, et chaque objet exécute les siennes :

func make_it_swim_and_quack(thing) -> void:
	print(thing.swim())
	print(thing.quack())
make_it_swim_and_quack(Duck.new())
make_it_swim_and_quack(Robot.new())
Duck swimming
Quack!
Robot swimming with propellers
Robot sound: BEEP BEEP!

La redéfinition nécessite une classe parent commune ; le typage canard, non. Avec le paramètre typé thing: Duck, passer un Robot provoquerait une erreur d’analyse.

Lorsqu’un objet ne possède pas la méthode, l’appel interrompt la fonction avec une erreur telle que Invalid call. Nonexistent function 'quack'. Vérifie d’abord avec has_method(), qui prend le nom de la méthode sous forme de String :

var things := [Duck.new(), Rock.new()]
for thing in things:
	if thing.has_method("quack"):
		print(thing.quack())
	else:
		print("This one cannot quack")
Quack!
This one cannot quack

Le prix à payer : avec les types, Godot détecte un nom de méthode incorrect avant l’exécution du programme ; avec le typage canard, tu ne le découvres que lorsque la ligne s’exécute. Utilise-le pour des objets de classes sans lien entre elles qui partagent quelques méthodes.

challenge icon

Défi

Facile

Une explosion endommage tout ce qui se trouve à proximité et peut subir des dégâts. Les objets n’ont aucune classe parente commune. player.gd et rock.gd sont terminés : un Player possède take_damage(amount) et status(), un Rock ne possède que status().

  • Dans crate.gd, donnez à Crate une variable broken qui vaut initialement false, une méthode take_damage(amount) qui casse la caisse lorsque la quantité de dégâts est égale ou supérieure à 10, et une méthode status() qui renvoie Crate: broken ou Crate: intact.
  • Dans explosion.gd, écrivez la méthode statique hit_all(things, amount). Elle appelle take_damage(amount) sur chaque objet du tableau Array qui possède cette méthode, puis renvoie le nombre d’objets touchés.

Le code fourni lit une ligne de noms d’objets (player, crate ou rock), puis le nombre d’explosions qui suivent et les dégâts infligés par chacune. Il affiche le nombre d’objets touchés par chaque explosion, puis le statut de chaque objet. Pour player crate rock et des explosions de 5 et 20, il affiche :

Explosion 1 hit 2 objects
Explosion 2 hit 2 objects
Player: 75 HP
Crate: broken
Rock: solid

Votre code va dans crate.gd et explosion.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 things := []
	for word in OS.read_string_from_stdin().split(" "):
		if word == "player":
			things.append(Player.new())
		elif word == "crate":
			things.append(Crate.new())
		else:
			things.append(Rock.new())
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var hits := Explosion.hit_all(things, int(OS.read_string_from_stdin()))
		print("Explosion %d hit %d objects" % [i + 1, hits])
	for thing in things:
		print(thing.status())
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