מחלקות פנימיות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 41 מתוך 65.
מחלקה יכולה להצהיר על מחלקה אחרת בתוכה, באמצעות מילת המפתח class, שם וגוף מוזח. מחלקה פנימית זו היא טיפוס עזר ששייך למחלקה החיצונית:
# inventory.gd
class_name Inventory
extends RefCounted
const MAX_STACK := 5
class Slot:
var item_name: String
var count: int
func _init(new_name: String, new_count: int) -> void:
item_name = new_name
count = mini(new_count, MAX_STACK)
func _to_string() -> String:
return "%s x%d" % [item_name, count]
var slots: Array[Slot] = []
func add(item_name: String, count: int) -> Slot:
var slot := Slot.new(item_name, count)
slots.append(slot)
return slotבתוך inventory.gd, המחלקה הפנימית היא Slot. כל קובץ אחר ניגש אליה דרך המחלקה החיצונית: Inventory.Slot.
# main.gd
var bag := Inventory.new()
bag.add("Potion", 9)
var arrows: Inventory.Slot = bag.add("Arrow", 3)
print(bag.slots) # [Potion x5, Arrow x3]
var gem := Inventory.Slot.new("Gem", 1)מחלקה פנימית ללא extends יורשת מ־RefCounted, והיא יכולה לכלול משתנים, בנאי ומתודות כמו כל מחלקה. היא יכולה להשתמש בקבועים וב-enum-ים של המחלקה החיצונית (MAX_STACK שלמעלה), אך לא במשתני החבר שלה: ל-Slot אין גישה ל-slots, מכיוון שמשבצת היא אובייקט נפרד. העבר לבנאי שלה כל ערך שהיא זקוקה לו.
השתמשו במחלקה פנימית עבור טיפוס קטן שיש לו משמעות רק יחד עם המחלקה החיצונית שלו, כמו משבצת במלאי או רשומה בטבלת ניקוד. טיפוס שחלקים אחרים במשחק משתמשים בו בפני עצמו ראוי לקובץ משלו ול־class_name.
אתגר
קלבנו Leaderboard שהרשומות שלו הן מחלקה פנימית.
- הכריזו על המחלקה הפנימית
EntryבתוךLeaderboard, כאשר הערכים שלplayer_nameו-scoreנקבעים על ידי הבנאי שלה, ו-_to_string()מחזירהAda: 120. entriesהוא מערך מטיפוסEntry, לפי סדר הופעת השחקנים לראשונה.submit(player, score)מוסיפה רשומה חדשה עבור שחקן חדש. עבור שחקן שכבר יש לו רשומה, היא שומרת את הגבוה מבין שני הציונים.best()מחזירה את הרשומה עם הציון הגבוה ביותר. במקרה של תיקו, הרשומה שמופיעה ראשונה זוכה.
הקוד שסופק קורא כמה ציונים מופיעים בהמשך (Ada 120), שולח אותם, ואז מדפיס כל רשומה ואת הרשומה הטובה ביותר (תמיד ניתן לפחות ציון אחד). עבור Ada 120, Bo 90, Ada 80, Bo 150, Cy 150 הוא מדפיס:
Ada: 120
Bo: 150
Cy: 150
Best: Bo: 150הקוד שלכם ייכנס ל-leaderboard.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
extends Node
func _ready():
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
var board := Leaderboard.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
board.submit(parts[0], int(parts[1]))
for entry in board.entries:
print(entry)
print("Best: ", board.best())
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידים8מושגי OOP מתקדמים
קומפוזיציה לעומת ירושהמחלקות פנימיותצמתים כרכיביםRefCounted לעומת NodeEnum במחלקותתרגלו בעצמכם: קומפיילר GDScript אונליין