Menu
CoddyTech

Public and Private Members

Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 26 of 65.

Encapsulation means an object keeps its data together with the methods that change that data, and decides which of its members other code may use. The members meant for other code form the object's interface.

GDScript has no public or private keyword: every member can be reached from outside. The Godot style guide marks the private ones with a leading underscore:

# bank_account.gd
class_name BankAccount
extends RefCounted

var owner_name: String
var _balance: int = 0
var _history: Array[String] = []

func _init(holder: String) -> void:
	owner_name = holder

func deposit(amount: int) -> void:
	_balance += amount
	_record("deposit %d" % amount)

func get_balance() -> int:
	return _balance

func _record(entry: String) -> void:
	_history.append(entry)

owner_name, deposit() and get_balance() are public, so main.gd uses them. _balance, _history and _record() are private: only the code inside bank_account.gd uses them.

# main.gd
var account := BankAccount.new("Ada")
account.deposit(50)
account.deposit(20)
print(account.owner_name) # Ada
print(account.get_balance()) # 70

The underscore is a convention, not a lock: account._balance = 1000000 in main.gd runs without any error. Keep to the convention anyway. When only the class changes _balance, a wrong balance can only come from a method in bank_account.gd, so that is the one file you have to check.

GDScript has no protected level either. A subclass inherits every member, private ones included, so a SavingsAccount that extends BankAccount can use _balance in its own methods.

Godot's virtual methods, such as _init() and _ready(), also start with an underscore. Godot calls them for you, so never give one of your private methods the same name.

challenge icon

Challenge

Easy

Finish the Hero class in hero.gd. Its public members are hero_name, gain_xp(), get_xp() and get_level(). The rest is private:

  • Add the private variables _xp (starts at 0) and _level (starts at 1).
  • Add the private method _update_level(), which sets _level to 1 + _xp / 100 (whole-number division).
  • gain_xp(amount) adds amount to _xp, calls _update_level() and returns true when the level went up, false otherwise.
  • get_xp() and get_level() return the private values.

The supplied code reads the hero's name, then how many XP amounts follow, then one amount per line. After each amount it prints a Level up! line when gain_xp() returns true, then the hero's state. For Ada and the amounts 40, 70 and 250 it prints:

Ada: 40 XP, level 1
Level up! Ada is now level 2
Ada: 110 XP, level 2
Level up! Ada is now level 4
Ada: 360 XP, level 4

Your code goes in hero.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 hero := Hero.new(OS.read_string_from_stdin())
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var amount := int(OS.read_string_from_stdin())
		if hero.gain_xp(amount):
			print("Level up! %s is now level %d" % [hero.hero_name, hero.get_level()])
		print("%s: %d XP, level %d" % [hero.hero_name, hero.get_xp(), hero.get_level()])
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