תבנית העיצוב
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 52 מתוך 65.
תבנית Decorator מוסיפה התנהגות לאובייקט על ידי עטיפתו באובייקט אחר עם אותן שיטות. כל עטיפה קוראת לאובייקט שבתוכה ומוסיפה את החלק שלה, ואפשר לערום עטיפות בכל סדר.
# weapon.gd
class_name Weapon
extends RefCounted
func get_damage() -> int:
return 10
func describe() -> String:
return "Sword"דקורטור מרחיב את Weapon, ולכן אפשר להשתמש בו בכל מקום שבו מצופה נשק, והוא מחזיק את הנשק שהוא עוטף:
# fire_enchant.gd
class_name FireEnchant
extends Weapon
var inner: Weapon
func _init(wrapped: Weapon) -> void:
inner = wrapped
func get_damage() -> int:
return inner.get_damage() + 5
func describe() -> String:
return inner.describe() + " + Fire"SharpEnchant נכתב באותו אופן, אבל get_damage() שלו מחזירה את inner.get_damage() * 2, והמתודה describe() שלו מוסיפה את " + Sharp".
# main.gd
var weapon: Weapon = Weapon.new()
print(weapon.describe(), ": ", weapon.get_damage())
weapon = FireEnchant.new(weapon)
weapon = SharpEnchant.new(weapon)
print(weapon.describe(), ": ", weapon.get_damage())Sword: 10
Sword + Fire + Sharp: 30הקריאות נעות פנימה: SharpEnchant פונה אל FireEnchant, שפונה אל החרב. החרב מחזירה 10, האש הופכת את הערך ל־15, והחדות מכפילה אותו ל־30. בסדר ההפוך, FireEnchant.new(SharpEnchant.new(Weapon.new())), הנזק הוא 10 * 2 + 5, כלומר 25.
בלי דקורטורים, כל שילוב היה דורש תת־מחלקה משלו: FireSword, SharpSword, FireSharpSword וכן הלאה. בעזרתם, שתי מחלקות קטנות מכסות את כל השילובים, והוספת קסם חדש דורשת קובץ אחד נוסף.
אתגר
בינוניבית קפה מכין משקאות באמצעות מעטרים. Beverage (beverage.gd) מצהירה על cost() ועל description(); הקוד עבור Espresso (espresso.gd, $3) ועבור Tea (tea.gd, $2) כבר נכתב. כל מעטר שומר את המשקה שהוא עוטף ב־inner (הבנאים כבר נכתבו). יש לדרוס את cost() ואת description() ב:
Milk: עולה1יותר ומוסיף+ Milkלתיאור.Mocha: עולה2יותר ומוסיף+ Mocha.Large: מכפיל את העלות של כל מה שבתוכו ומוסיףLargeלפני התיאור.
הקוד שסופק קורא כמה הזמנות מופיעות בהמשך, ואז הזמנה אחת בכל שורה: המשקה (espresso או tea) והתוספות שלו, המיושמות משמאל לימין. עבור espresso milk large ועבור tea mocha milk הפלט הוא:
Large Espresso + Milk: $8
Tea + Mocha + Milk: $5יש לכתוב את הקוד שלך בקבצים milk.gd, mocha.gd ו־large.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
extends Node
func _ready():
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
var count := int(OS.read_string_from_stdin())
for i in count:
var words := OS.read_string_from_stdin().split(" ")
var drink: Beverage = Tea.new()
if words[0] == "espresso":
drink = Espresso.new()
for extra in words.slice(1):
match extra:
"milk":
drink = Milk.new(drink)
"mocha":
drink = Mocha.new(drink)
"large":
drink = Large.new(drink)
print("%s: $%d" % [drink.description(), drink.cost()])
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידיםתרגלו בעצמכם: קומפיילר GDScript אונליין