Walidacja za pomocą setterów
Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 27 z 65.
Setter jest uruchamiany za każdym razem, gdy przypisywana jest wartość jego właściwości, dlatego to właśnie w nim należy sprawdzać nową wartość. Python zgłasza błąd w przypadku nieprawidłowej wartości. GDScript nie obsługuje wyjątków, więc setter robi zamiast tego jedną z dwóch rzeczy: ogranicza wartość do zakresu albo zachowuje starą wartość i zapisuje, co poszło nie tak.
# 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 = valueclampi(value, 0, 100) zwraca value ograniczone do zakresu od 0 do 100. W setterze nickname instrukcja return kończy działanie przed przypisaniem, więc poprzednia nazwa pozostaje, a last_error wyjaśnia dlaczego:
# 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) # AliceSetter działa również przy przypisaniach wewnątrz klasy, w _init() i w każdej metodzie. Przypisz argumenty konstruktora za pomocą właściwości, a one również zostaną sprawdzone:
func _init(start_hp: int) -> void:
hp = start_hp # wywołuje setter: Character.new(500) zaczyna z wartością 100W samym setterze przypisanie hp zapisuje wartość bez ponownego wywoływania settera. Jedynym przypisaniem, które pomija setter, jest wartość początkowa w deklaracji (= 100), więc ta wartość musi być poprawna sama w sobie.
Wyzwanie
ŁatwyDodaj walidację do klasy Thermostat w pliku thermostat.gd za pomocą setterów:
target(początkowo20) przyjmuje tylko wartości od10do30. Dla każdej innej wartości zachowuje poprzednią wartość docelową i ustawialast_errornaTarget must be between 10 and 30.mode(początkowooff) przyjmuje tylko wartościheat,coolioff. Dla każdego innego tekstu zachowuje poprzedni tryb i ustawialast_errornaUnknown mode:, po którym następuje ten tekst.- Poprawne przypisanie ustawia
last_errorz powrotem na pusty ciąg znaków. _init(start_target)przypisujestart_targetdotarget, dzięki czemu wartość jest sprawdzana przez setter.
Dostarczony kod odczytuje początkową wartość docelową, następnie liczbę poleceń, a potem jedno polecenie w każdym wierszu (target 25 lub mode cool). Po utworzeniu termostatu i po każdym poleceniu wypisuje Rejected: i błąd, gdy last_error nie jest pusty, a następnie stan. Dla początkowej wartości 22 i poleceń target 35 oraz mode cool wypisuje:
Target 22, mode off
Rejected: Target must be between 10 and 30
Target 22, mode off
Target 22, mode coolTwój kod umieść w pliku thermostat.gd. Plik main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
extends Node
func _ready():
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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])
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe selfMetodyWłaściwościKonstruktor (_init)Powtórka – prosty kalkulator4Polimorfizm
Ponowne omówienie przesłaniania metodDuck typingKlasy i metody abstrakcyjneProjektowanie interfejsówPowtórzenie – kalkulator kształtów7Sygnały
Czym jest sygnał?Deklarowanie i emitowanieŁączenie z sygnałamiSygnały z argumentamiPodsumowanie — system zdrowia10Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu2Właściwości klas
Zmienne instancji a zmienne statyczneFunkcje statyczneSettery właściwościGettery właściwościPrywatne z konwencjiPodsumowanie — menedżer kont bankowych5Enkapsulacja
Elementy publiczne i prywatneWalidacja za pomocą setterówUkrywanie informacjiWłaściwości tylko do odczytuPodsumowanie – system ewidencji uczniów8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieKlasy wewnętrzneWęzły jako komponentyRefCounted a NodeTypy wyliczeniowe w klasach11Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superNadpisywanie metodŁańcuchy dziedziczeniaSprawdzanie typów za pomocą isPodsumowanie – hierarchia pracowników6Metody specjalne
Wprowadzenie do metod wirtualnychMetoda _to_stringWłasne iteratoryPodsumowanie — własna lista9Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator GDScript online