Menu
CoddyTech

Проверка данных с помощью сеттеров

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

Сеттер выполняется каждый раз, когда свойству присваивается значение, поэтому именно здесь нужно проверять новое значение. Python вызывает ошибку при недопустимом значении. В GDScript нет исключений, поэтому сеттер вместо этого делает одно из двух: ограничивает значение допустимым диапазоном или сохраняет прежнее значение и записывает, что пошло не так.

# 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 = value

clampi(value, 0, 100) возвращает value, ограниченное диапазоном от 0 до 100. В сеттере nickname ключевое слово return завершает выполнение до присваивания, поэтому старое имя сохраняется, а last_error объясняет причину:

# 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) # Alice

Сеттер также запускается при присваиваниях внутри класса, в _init() и в каждом методе. Передавай аргументы конструктора через свойство — они тоже будут проверены:

func _init(start_hp: int) -> void:
	hp = start_hp # вызывает сеттер: Character.new(500) начинает со 100

Внутри самого сеттера присваивание hp сохраняет значение, не вызывая сеттер повторно. Единственное присваивание, которое пропускает сеттер, — это начальное значение в объявлении (= 100), поэтому это значение должно быть допустимым само по себе.

challenge icon

Задание

Легко

Добавь проверку корректности в класс Thermostat в файле thermostat.gd с помощью сеттеров:

  • target (начальное значение — 20) принимает только значения от 10 до 30. Для любого другого значения он сохраняет прежнее значение и устанавливает last_error в Target must be between 10 and 30.
  • mode (начальное значение — off) принимает только heat, cool и off. Для любого другого текста он сохраняет прежнее значение и устанавливает last_error в Unknown mode: , после которого добавляется этот текст.
  • При допустимом присваивании last_error снова устанавливается в пустую строку.
  • _init(start_target) присваивает start_target переменной target, поэтому для него выполняется проверка сеттером.

Предоставленный код считывает начальное значение целевой температуры, затем количество команд, а потом по одной команде в каждой строке (target 25 или mode cool). После создания термостата и после каждой команды он выводит Rejected: и сообщение об ошибке, если last_error не пуст, а затем — состояние. Для начального значения 22 и команд target 35 и mode cool вывод будет таким:

Target 22, mode off
Rejected: Target must be between 10 and 30
Target 22, mode off
Target 22, mode cool

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

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

extends Node

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

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

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

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