Menu
CoddyTech

אימות באמצעות Setters

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 27 מתוך 65.

Setter מופעל בכל פעם שמקצים ערך למאפיין שלו, ולכן זה המקום לבדוק את הערך החדש. Python מעלה שגיאה עבור ערך לא תקין. ל-GDScript אין חריגות, ולכן setter עושה במקום זאת אחד מהדברים הבאים: הוא מגביל את הערך לטווח, או שומר על הערך הישן ומתעד מה השתבש.

# 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

ה-setter מופעל גם בהשמות בתוך המחלקה, ב-_init() ובכל מתודה. השם את הארגומנטים של הבנאי דרך המאפיין, וגם הם ייבדקו:

func _init(start_hp: int) -> void:
	hp = start_hp # מפעיל את ה-setter: ‏Character.new(500) מתחיל עם 100

בתוך ה-setter עצמו, השמה של hp מאחסנת את הערך בלי לקרוא שוב ל-setter. ההשמה היחידה שמדלגת על ה-setter היא הערך ההתחלתי בהצהרה (= 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 אונליין