Menu
CoddyTech

Classes et méthodes abstraites

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

Certaines classes existent uniquement pour être étendues. Chaque forme a une aire, mais vous ne pouvez pas la calculer tant que vous ne savez pas s’il s’agit d’un cercle ou d’un rectangle. Marquez une telle classe avec @abstract, sur la ligne au-dessus de class_name :

# shape.gd
@abstract
class_name Shape
extends RefCounted

@abstract func area() -> float
@abstract func perimeter() -> float

func describe() -> String:
	return "Area %.1f, perimeter %.1f" % [area(), perimeter()]

Un @abstract func possède une signature et aucun corps : pas de deux-points ni de code après lui. Cela signifie que chaque classe enfant doit fournir cette méthode. describe() est une méthode normale ; les classes enfants en héritent, et elle peut déjà appeler les méthodes abstraites.

Tu ne peux pas créer d’objet d’une classe abstraite. Shape.new() arrête le programme avant son démarrage avec Parse Error: Cannot construct abstract class "Shape".

Une classe enfant qui écrit toutes les méthodes abstraites est une classe normale :

# rectangle.gd
class_name Rectangle
extends Shape

var width: float
var height: float

func _init(w: float, h: float) -> void:
	width = w
	height = h

func area() -> float:
	return width * height

func perimeter() -> float:
	return 2 * (width + height)
var rect := Rectangle.new(4.0, 6.0)
print(rect.describe())
Area 24.0, perimeter 20.0

Si une classe enfant en omet une, Godot le signale avant l’exécution : Class "Square" must implement "Shape.perimeter()" and other inherited abstract methods or be marked as "@abstract". Ainsi, chaque objet que tu peux créer possède area() et perimeter().

Une classe abstraite peut tout de même avoir des variables et un _init(). Les classes enfants l’appellent avec super() comme d’habitude.

challenge icon

Défi

Facile

Une boutique accepte deux modes de paiement. Chaque paiement comporte un montant et un reçu, mais les frais et le nom dépendent du mode.

  • Faites de PaymentMethod une classe abstraite et déclarez deux méthodes abstraites : fee() -> float et method_name() -> String. Écrivez receipt(), qui renvoie NAME: paid AMOUNT, fee FEE, total TOTAL avec deux décimales pour chaque nombre (le total correspond au montant plus les frais).
  • CreditCard : les frais correspondent à 3 % du montant (amount * 0.03), et le nom est Credit card.
  • BankTransfer : les frais sont de 1.5, ou de 0.0 lorsque le montant est supérieur ou égal à 100, et le nom est Bank transfer.

Les classes dérivées utilisent le constructeur de PaymentMethod. Le code fourni lit le nombre de paiements à venir, puis une ligne par paiement : card AMOUNT ou transfer AMOUNT. Il affiche chaque reçu et la somme des frais. Pour card 50 et transfer 120, il affiche :

Credit card: paid 50.00, fee 1.50, total 51.50
Bank transfer: paid 120.00, fee 0.00, total 120.00
Total fees: 1.50

Votre code doit être placé dans payment_method.gd, credit_card.gd et bank_transfer.gd. main.gd contient le code fourni pour les entrées/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 count := int(OS.read_string_from_stdin())
	var total_fees := 0.0
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		var payment: PaymentMethod
		if p[0] == "card":
			payment = CreditCard.new(float(p[1]))
		else:
			payment = BankTransfer.new(float(p[1]))
		print(payment.receipt())
		total_fees += payment.fee()
	print("Total fees: %.2f" % total_fees)
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