Validation with Setters
Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 27 of 65.
A setter runs every time its property is assigned, which makes it the place to check the new value. Python raises an error for a bad value. GDScript has no exceptions, so a setter does one of these instead: it clamps the value into range, or it keeps the old value and records what went wrong.
# character.gd
class_name Character
extends RefCounted
var last_error: String = ""
var hp: int = 100:
set(value):
hp = clampi(value, 0, 100)
var nickname: String = "Player":
set(value):
if value.length() < 3:
last_error = "Name too short"
return
last_error = ""
nickname = valueclampi(value, 0, 100) returns value moved into the range 0 to 100. In the nickname setter, return leaves before the assignment, so the old name stays and last_error explains why:
# main.gd
var hero := Character.new()
hero.hp = 250
print(hero.hp) # 100
hero.nickname = "Al"
print(hero.nickname) # Player
print(hero.last_error) # Name too short
hero.nickname = "Alice"
print(hero.nickname) # AliceThe setter also runs for assignments inside the class, in _init() and in every method. Assign the constructor's arguments through the property and they are checked as well:
func _init(start_hp: int) -> void:
hp = start_hp # runs the setter: Character.new(500) starts with 100Inside the setter itself, assigning hp stores the value without calling the setter again. The one assignment that skips the setter is the initial value in the declaration (= 100), so that value must be valid on its own.
Challenge
EasyAdd validation to the Thermostat class in thermostat.gd with setters:
target(starts at20) accepts only values from10to30. For any other value it keeps the old target and setslast_errortoTarget must be between 10 and 30.mode(starts atoff) accepts onlyheat,coolandoff. For any other text it keeps the old mode and setslast_errortoUnknown mode:followed by the text.- A valid assignment sets
last_errorback to an empty string. _init(start_target)assignsstart_targettotarget, so the setter checks it.
The supplied code reads the starting target, then the number of commands, then one command per line (target 25 or mode cool). After creating the thermostat and after each command it prints Rejected: and the error when last_error is not empty, then the state. For the start 22 and the commands target 35 and mode cool it prints:
Target 22, mode off
Rejected: Target must be between 10 and 30
Target 22, mode off
Target 22, mode coolYour code goes in thermostat.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 thermostat := Thermostat.new(int(OS.read_string_from_stdin()))
report(thermostat)
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "target":
thermostat.target = int(parts[1])
else:
thermostat.mode = parts[1]
report(thermostat)
func report(thermostat: Thermostat) -> void:
if thermostat.last_error != "":
print("Rejected: " + thermostat.last_error)
print("Target %d, mode %s" % [thermostat.target, thermostat.mode])
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