Duck Typing
Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 22 of 65.
Duck typing cares about what an object can do, not which class it belongs to. If it has the method you call, the call works. The name comes from the saying "if it swims like a duck and quacks like a duck, it is a duck".
These two classes share no parent of their own, but both have swim() and 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!"A parameter without a type accepts any object. The function calls the methods, and each object runs its own:
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!Overriding needs a shared parent class; duck typing does not. With the parameter typed thing: Duck, passing a Robot would be a parse error.
When an object lacks the method, the call stops the function with an error such as Invalid call. Nonexistent function 'quack'. Ask first with has_method(), which takes the method name as a 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 quackThe price: with types, Godot finds a wrong method name before the program runs; with duck typing you find out only when the line runs. Use it for objects of unrelated classes that share a few methods.
Challenge
EasyAn explosion damages everything nearby that can take damage. The objects share no parent class. player.gd and rock.gd are finished: a Player has take_damage(amount) and status(), a Rock only status().
- In
crate.gd, giveCrateabrokenvariable that startsfalse, atake_damage(amount)method that breaks the crate when the amount is10or more, andstatus()returningCrate: brokenorCrate: intact. - In
explosion.gd, write the statichit_all(things, amount). It callstake_damage(amount)on every object in the Array that has that method, and returns how many it hit.
The supplied code reads a line of object names (player, crate or rock), then how many explosions follow and the damage of each. It prints how many objects each explosion hit, then every object's status. For player crate rock and explosions of 5 and 20 it prints:
Explosion 1 hit 2 objects
Explosion 2 hit 2 objects
Player: 75 HP
Crate: broken
Rock: solidYour code goes in crate.gd and explosion.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 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())
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