Virtual Methods Introduction
Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 31 of 65.
Python has magic methods such as __init__ and __str__, which the language calls for you. Godot's version is the virtual method: a method with a fixed name, starting with an underscore, that you define in your class and Godot calls at the right moment. You have used two already:
_init()runs whennew()creates the object, with the arguments given tonew()._ready()runs when a node enters the scene tree, which is wheremain.gdstarts.
Others are _to_string(), called when an object is printed, the iterator methods that let a for loop walk through an object (both in the next lessons), and _notification(), which receives events from the engine. One of them, NOTIFICATION_PREDELETE, arrives right before the object is deleted:
# 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") # Hall torch lit
torch = null # Hall torch burned outA RefCounted object is deleted as soon as no variable refers to it any more, so torch = null sends the notification at once. The default value in _init() makes the argument of new() optional: Torch.new() creates a torch called Torch.
Python also uses magic methods for operators, such as __add__ for + and __eq__ for ==. GDScript has no operator overloading: potion_a + potion_b is an error. Write a method instead:
# 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) returns a new potion and leaves both originals unchanged. == between two objects checks whether both sides are the same object, not whether their values match: Potion.new(5) == Potion.new(5) is false. Write a method such as equals(other) when you need to compare values.
Challenge
EasyWrite the Counter class in counter.gd:
_init(start = 0, step_size = 1)stores the start invalueand the step size instep. The defaults are already in the signature, soCounter.new(),Counter.new(5)andCounter.new(5, 2)all work.tick()addssteptovalue.plus(other)replaces the+operator, which GDScript does not let you define: it returns a newCounterwhose value is the sum of both values and whose step is this counter's step. Neither counter changes.equals(other)returnstruewhen both counters have the same value.
The supplied code reads two lines that create the counters a and b (an empty line, START or START STEP), then one line with how many times to tick a and b. It prints both counters, their sum, whether their values are equal and whether a == b. For the lines 5, 2 3 and 3 1 it prints:
a: 8 (step 1)
b: 5 (step 3)
a plus b: 13 (step 1)
same value: false
same object: falseYour code goes in counter.gd. main.gd holds the supplied input/output code and cannot be edited.
Try it yourself
extends Node
func _ready():
# Supplied input/output code: keep it as it is
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]))
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe self KeywordMethodsPropertiesConstructor (_init)Recap - Simple Calculator4Polymorphism
Method Overriding RevisitedDuck TypingAbstract Classes and MethodsInterface DesignRecap - Shape Calculator2Class Properties
Instance vs Static VariablesStatic FunctionsProperty SettersProperty GettersPrivate by ConventionRecap - Bank Account Manager5Encapsulation
Public and Private MembersValidation with SettersInformation HidingRead-Only PropertiesRecap - Student Records System8Advanced OOP Concepts
Composition vs InheritanceInner ClassesNodes as ComponentsRefCounted vs NodeEnums in Classes11Project: Library Management
Project OverviewBook and User Classes3Inheritance
Basic InheritanceThe super KeywordMethod OverridingInheritance ChainsType Checks with isRecap - Employee Hierarchy6Special Methods
Virtual Methods IntroductionThe _to_string MethodCustom IteratorsRecap - Custom List9Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy PatternPractice on your own: Online GDScript compiler