תבנית המצב
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 54 מתוך 65.
תבנית State מעניקה לאובייקט אובייקט מצב נפרד עבור כל מצב שבו הוא יכול להיות. האובייקט מעביר את העבודה שלו למצב הנוכחי, ולכן ההתנהגות שלו משתנה כשהמצב משתנה.
עבור מספר קטן של מצבים, enum ו-match מספיקים. כשכל מצב מגיב לכמה פעולות בדרכו שלו, אותו match גדל עם כל מצב וכל פעולה. תבנית State מעבירה את הכללים של כל מצב למחלקה משלו:
# hero_state.gd
@abstract
class_name HeroState
extends RefCounted
@abstract func get_state_name() -> String
@abstract func handle(action: String) -> HeroStatehandle() מחזירה את המצב הבא: אובייקט מצב חדש לעבור אליו, או self כדי להישאר.
# idle_state.gd
class_name IdleState
extends HeroState
func get_state_name() -> String:
return "Idle"
func handle(action: String) -> HeroState:
if action == "run":
return RunState.new()
return selfגם RunState נכתב באותו אופן: שמו הוא "Running", ו-"stop" מחזיר IdleState.new(). הגיבור, ההקשר, שומר את המצב הנוכחי ושואל אותו מה לעשות:
# hero.gd
class_name Hero
extends RefCounted
var state: HeroState = IdleState.new()
func handle_action(action: String) -> void:
var next := state.handle(action)
if next != state:
print(state.get_state_name(), " -> ", next.get_state_name())
state = next# main.gd
var hero := Hero.new()
for action in ["stop", "run", "run", "stop"]:
hero.handle_action(action)Idle -> Running
Running -> Idleלאותה פעולה יש משמעויות שונות במצבים שונים: "stop" לא עושה דבר כשהדמות במצב המתנה, ועוצר גיבור שרץ. כל כלל נמצא במחלקה של המצב שלו, כך שמצב חדש, כמו קפיצה, הוא מחלקה חדשה אחת.
המצבים מחזירים את המצב הבא במקום לאחסן את הגיבור. מצב שמחזיק את הגיבור בזמן שהגיבור מחזיק את המצב היה יוצר מעגל הפניות, ואף אחד מהאובייקטים לא היה משתחרר לעולם.
אתגר
קלדלת יכולה להיות Locked, Closed או Open. DoorState (door_state.gd) מצהירה על get_state_name() ועל handle(action), ו-LockedState (locked_state.gd) כבר כתובה: unlock מעביר את הדלת למצב Closed. כתבו:
ClosedState.handle(): הפעולהopenמחזירהOpenStateחדש, הפעולהlockמחזירהLockedStateחדש, וכל פעולה אחרת מחזירהself.OpenState.handle(): הפעולהcloseמחזירהClosedStateחדש, וכל פעולה אחרת מחזירהself.Door.handle_action(action): מבקשת מהמצב הנוכחי את המצב הבא. אם זה אותו אובייקט, הדפיסוACTION: still STATE; אחרת הדפיסוACTION: OLD -> NEWועברו למצב החדש.
הדלת מתחילה במצב Locked. הקוד שסופק קורא כמה פעולות יגיעו, ואז פעולה אחת בכל שורה, ומדפיס את המצב הסופי. עבור open, unlock, open, lock הפלט הוא:
open: still Locked
unlock: Locked -> Closed
open: Closed -> Open
lock: still Open
Final state: Openהקוד שלכם נמצא בקבצים door.gd, closed_state.gd ו-open_state.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
extends Node
func _ready():
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
var door := Door.new()
var count := int(OS.read_string_from_stdin())
for i in count:
door.handle_action(OS.read_string_from_stdin())
print("Final state: ", door.state.get_state_name())
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידיםתרגלו בעצמכם: קומפיילר GDScript אונליין