Menu
CoddyTech

Validación con setters

Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 27 de 65.

Un setter se ejecuta cada vez que se asigna un valor a su propiedad, por lo que es el lugar adecuado para comprobar el nuevo valor. Python genera un error si el valor no es válido. GDScript no tiene excepciones, así que un setter hace una de estas cosas: limita el valor al rango permitido o conserva el valor anterior y registra qué salió mal.

# 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) devuelve value ajustado al rango de 0 a 100. En el setter de nickname, return sale antes de la asignación, así que se conserva el nombre anterior y last_error explica el motivo:

# main.gd
var hero := Character.new()
hero.hp = 250
print(hero.hp) # 100
hero.nickname = "Al"
print(hero.nickname) # Player
print(hero.last_error) # Nombre demasiado corto
hero.nickname = "Alice"
print(hero.nickname) # Alice

El setter también se ejecuta para las asignaciones dentro de la clase, en _init() y en todos los métodos. Asigna los argumentos del constructor a través de la propiedad y también se comprobarán:

func _init(start_hp: int) -> void:
	hp = start_hp # ejecuta el setter: Character.new(500) empieza con 100

Dentro del propio setter, asignar hp almacena el valor sin volver a llamar al setter. La única asignación que omite el setter es el valor inicial en la declaración (= 100), así que ese valor debe ser válido por sí solo.

challenge icon

Desafío

Fácil

Añade validación a la clase Thermostat en thermostat.gd con setters:

  • target (empieza en 20) solo acepta valores de 10 a 30. Para cualquier otro valor, conserva el objetivo anterior y establece last_error en Target must be between 10 and 30.
  • mode (empieza en off) solo acepta heat, cool y off. Para cualquier otro texto, conserva el modo anterior y establece last_error en Unknown mode: seguido del texto.
  • Una asignación válida restablece last_error a una cadena vacía.
  • _init(start_target) asigna start_target a target, para que el setter lo compruebe.

El código proporcionado lee el objetivo inicial, después el número de comandos y, después, un comando por línea (target 25 o mode cool). Después de crear el termostato y después de cada comando, imprime Rejected: y el error cuando last_error no está vacío, y luego el estado. Para el valor inicial 22 y los comandos target 35 y mode cool, imprime:

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

Tu código va en thermostat.gd. main.gd contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

extends Node

func _ready():
	# Código de entrada/salida proporcionado: mantenlo tal como está
	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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de GDScript online