אימות באמצעות 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 = valueclampi(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), ולכן הערך הזה חייב להיות תקין בפני עצמו.
אתגר
קלהוסף אימות למחלקה 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])
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידיםתרגלו בעצמכם: קומפיילר GDScript אונליין