Menu
CoddyTech

Einführung in virtuelle Methoden

Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 31 von 65.

Python hat magische Methoden wie __init__ und __str__, die von der Sprache für dich aufgerufen werden. In Godot gibt es dafür die virtuelle Methode: eine Methode mit einem festen Namen, der mit einem Unterstrich beginnt und die du in deiner Klasse definierst. Godot ruft sie zum richtigen Zeitpunkt auf. Du hast bereits zwei verwendet:

  • _init() wird ausgeführt, wenn new() das Objekt erstellt, und erhält die an new() übergebenen Argumente.
  • _ready() wird ausgeführt, wenn ein Node in den Szenenbaum eintritt. Dort beginnt main.gd.

Andere sind _to_string(), das aufgerufen wird, wenn ein Objekt ausgegeben wird, die Iteratormethoden, mit denen eine for-Schleife ein Objekt durchlaufen kann (beides in den nächsten Lektionen), und _notification(), das Ereignisse von der Engine empfängt. Eines davon, NOTIFICATION_PREDELETE, tritt unmittelbar vor dem Löschen des Objekts ein:

# 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") # Flurfackel angezündet
torch = null # Flurfackel ausgebrannt

Ein RefCounted-Objekt wird gelöscht, sobald keine Variable mehr darauf verweist. Daher sendet torch = null die Benachrichtigung sofort. Der Standardwert in _init() macht das Argument von new() optional: Torch.new() erstellt eine Fackel namens Torch.

Python verwendet ebenfalls magische Methoden für Operatoren, wie __add__ für + und __eq__ für ==. GDScript unterstützt keine Operatorüberladung: potion_a + potion_b ist ein Fehler. Schreibe stattdessen eine Methode:

# 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) gibt einen neuen Trank zurück und lässt beide ursprünglichen unverändert. == zwischen zwei Objekten prüft, ob beide Seiten dasselbe Objekt sind, nicht ob ihre Werte übereinstimmen: Potion.new(5) == Potion.new(5) ist false. Schreibe eine Methode wie equals(other), wenn du Werte vergleichen musst.

challenge icon

Aufgabe

Einfach

Schreibe die Klasse Counter in counter.gd:

  • _init(start = 0, step_size = 1) speichert den Startwert in value und die Schrittweite in step. Die Standardwerte stehen bereits in der Signatur, daher funktionieren Counter.new(), Counter.new(5) und Counter.new(5, 2).
  • tick() addiert step zu value.
  • plus(other) ersetzt den +-Operator, dessen Definition GDScript nicht zulässt: Die Methode gibt einen neuen Counter zurück, dessen Wert die Summe beider Werte und dessen Schrittweite die Schrittweite dieses Zählers ist. Keiner der beiden Zähler wird verändert.
  • equals(other) gibt true zurück, wenn beide Zähler denselben Wert haben.

Der bereitgestellte Code liest zwei Zeilen ein, die die Zähler a und b erstellen (eine leere Zeile, START oder START STEP), gefolgt von einer Zeile mit der Anzahl der Ticks für a und b. Er gibt beide Zähler, ihre Summe, die Gleichheit ihrer Werte und die Information aus, ob a == b gilt. Für die Zeilen 5, 2 3 und 3 1 gibt er Folgendes aus:

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

Dein Code gehört in counter.gd. main.gd enthält den bereitgestellten Eingabe-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

extends Node

func _ready():
	# Vorgegebener Ein-/Ausgabecode: unverändert lassen
	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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-GDScript-Compiler