Menu
CoddyTech

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 true

main.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 icon

Challenge

Easy

Write 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 returns true. If the title is already in the playlist, it changes nothing and returns false.
  • remove(title) removes the title and returns true, or returns false when 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, Rain

Your 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()))
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Online GDScript compiler