Information Hiding
Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 28 of 65.
Information hiding goes one step further than private variables: code that uses a class depends only on what its public methods do, never on how the class stores its data. Then you can change the storage without touching that code.
# inventory.gd
class_name Inventory
extends RefCounted
var _counts: Dictionary = {}
func add(item: String, amount: int) -> void:
_counts[item] = _counts.get(item, 0) + amount
func count(item: String) -> int:
return _counts.get(item, 0)
func remove(item: String, amount: int) -> bool:
if count(item) < amount:
return false
_counts[item] -= amount
return truemain.gd calls add(), count() and remove() and never sees the Dictionary. If Inventory later keeps an Array of slots instead, only inventory.gd changes.
Be careful with getters that return an Array or a Dictionary. GDScript hands out these values by reference: the caller gets the object's own Array, not a copy, and can change it without going through the class's methods:
# quest_log.gd
var _quests: Array[String] = ["Find the key"]
func get_quests() -> Array[String]:
return _quests# main.gd
var journal := QuestLog.new()
var quests := journal.get_quests()
quests.append("Skip the boss")
print(journal.get_quests()) # ["Find the key", "Skip the boss"]Return a copy instead. duplicate() makes a new Array with the same elements, so changes to it stay outside the object:
func get_quests() -> Array[String]:
return _quests.duplicate()For a Dictionary, or an Array that holds other Arrays, use duplicate(true): it copies the inner Arrays and Dictionaries too.
Challenge
EasyWrite the Playlist class in playlist.gd. It keeps the song titles in the private Array _songs, and other code uses only these methods:
add(title)appends the title and returnstrue. If the title is already in the playlist, it changes nothing and returnsfalse.remove(title)removes the title and returnstrue, or returnsfalsewhen it is not there.count()returns the number of songs.get_titles()returns a copy of the titles, in the order they were added.
The supplied code reads the number of commands, then one command per line (add Blue Sky or remove Blue Sky) and prints the result. At the end it takes the Array from get_titles(), appends Intruder and reverses it, then prints the song count and the titles. Your playlist must not be affected by those changes. For the commands add Blue Sky, add Rain and add Blue Sky it prints:
Added: Blue Sky
Added: Rain
Already in the playlist: Blue Sky
Songs: 2
Blue Sky, RainYour code goes in playlist.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 playlist := Playlist.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ", true, 1)
var title := parts[1]
if parts[0] == "add":
if playlist.add(title):
print("Added: " + title)
else:
print("Already in the playlist: " + title)
elif playlist.remove(title):
print("Removed: " + title)
else:
print("Not found: " + title)
# Code that tries to change the list it gets back
var titles := playlist.get_titles()
titles.append("Intruder")
titles.reverse()
print("Songs: %d" % playlist.count())
print(", ".join(playlist.get_titles()))
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