Menu
CoddyTech

Открытые и закрытые члены

Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 26 из 65.

Инкапсуляция означает, что объект хранит свои данные вместе с методами, которые изменяют эти данные, и определяет, какие его члены может использовать другой код. Члены, предназначенные для другого кода, образуют интерфейс объекта.

В GDScript нет ключевых слов public или private: к каждому члену можно обратиться извне. В руководстве по стилю Godot приватные члены обозначаются начальным символом подчёркивания:

# 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() и get_balance() являются общедоступными, поэтому они используются в main.gd. _balance, _history и _record() являются приватными: их использует только код внутри bank_account.gd.

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

Подчёркивание — это соглашение, а не блокировка: account._balance = 1000000 в main.gd выполняется без ошибок. Всё равно придерживайся этого соглашения. Если только класс изменяет _balance, неправильный баланс может появиться только из-за метода в bank_account.gd, поэтому проверить нужно именно этот файл.

В GDScript тоже нет уровня protected. Подкласс наследует все члены, включая приватные, поэтому SavingsAccount, который extends BankAccount, может использовать _balance в своих методах.

Виртуальные методы Godot, такие как _init() и _ready(), тоже начинаются с символа подчёркивания. Godot вызывает их за вас, поэтому никогда не давайте своим приватным методам такие же имена.

challenge icon

Задание

Легко

Заверши класс Hero в файле hero.gd. Его открытые члены — hero_name, gain_xp(), get_xp() и get_level(). Остальные — закрытые:

  • Добавь закрытые переменные _xp (начинается с 0) и _level (начинается с 1).
  • Добавь закрытый метод _update_level(), который устанавливает значение _level равным 1 + _xp / 100 (целочисленное деление).
  • gain_xp(amount) добавляет amount к _xp, вызывает _update_level() и возвращает true, если уровень повысился, и false в противном случае.
  • get_xp() и get_level() возвращают закрытые значения.

Предоставленный код считывает имя героя, затем количество следующих значений XP, а затем по одному значению в каждой строке. После каждого значения он выводит строку Level up!, если gain_xp() возвращает true, а затем выводит состояние героя. Для Ada и значений 40, 70 и 250 он выводит:

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

Твой код нужно поместить в hero.gd. В main.gd находится предоставленный код ввода/вывода, и его нельзя редактировать.

Попробуйте сами

extends Node

func _ready():
	# Предоставленный код ввода/вывода: оставьте его без изменений
	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 iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор GDScript