שרשראות ירושה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 18 מתוך 65.
מחלקת ילד יכולה בעצמה להיות מחלקת אב. כל extends מוסיף רמה אחת לשרשרת הירושה:
# vehicle.gd
class_name Vehicle
extends RefCounted
var wheels: int
func _init(w: int) -> void:
wheels = w
func describe() -> String:
return "%d wheels" % wheels# car.gd
class_name Car
extends Vehicle
func _init() -> void:
super(4)
func describe() -> String:
return "Car with " + super()# race_car.gd
class_name RaceCar
extends Car
var top_speed: int
func _init(speed: int) -> void:
super()
top_speed = speed
func describe() -> String:
return super() + ", top speed %d" % top_speedל־RaceCar יש את כל מה שיש ב־Car וב־Vehicle. כל קריאה ל־super() עולה רמה אחת, כך שקריאה אחת מריצה את כל שלוש הגרסאות של describe():
print(RaceCar.new(300).describe())Car with 4 wheels, top speed 300כשקוראים למתודה או קוראים את הערך של משתנה, Godot מחפש תחילה במחלקה של האובייקט עצמו, אחר כך במחלקת האב שלו, ואז במחלקת האב של מחלקת האב, ומשתמש בראשון שהוא מוצא. RaceCar.new(300).wheels נמצא ב-Vehicle, שתי רמות למעלה.
לכל מחלקה יש בדיוק מחלקת אב אחת. extends מקבלת מחלקה אחת, ורישום של שתיים הוא שגיאת ניתוח:
class_name FlyingCar
extends Car, PlaneParse Error: Expected end of statement after superclass, found "," instead.ל-GDScript אין ירושה מרובה. כשמחלקה זקוקה לתכונות של שתי מחלקות, הציבו אותן באותה שרשרת, או תנו לה אובייקט מהמחלקה האחרת לעבוד איתו (פרק מאוחר יותר עוסק בכך).
אתגר
קלcharacter.gd מכיל את המחלקה המוגמרת Character: שם, hp, הפונקציה describe() שמחזירה NAME (HP HP) והפונקציה attack() שמחזירה 1. בנו עליו עוד שתי רמות:
Warriorיורשת מ־Characterומוסיפה אתstrength. הבנאי שלה מעביר את השם ואת hp אלsuper(). הפונקציהdescribe()מוסיפה, strength Sלטקסט של מחלקת האב, והפונקציהattack()מחזירה את הכוח.Knightיורשת מ־Warriorומוסיפה אתarmor. הבנאי שלה מעביר את השם, את hp ואת הכוח אלsuper(). הפונקציהdescribe()מוסיפה, armor Aלטקסט שלWarrior, והפונקציהattack()מחזירה את ההתקפה שלWarriorועוד5.
הקוד שסופק קורא כמה דמויות יופיעו, ולאחר מכן שורה אחת לכל דמות: character NAME HP, warrior NAME HP STRENGTH או knight NAME HP STRENGTH ARMOR. הוא מדפיס את describe() ואת ההתקפה. עבור knight Arthur 120 15 8 הוא מדפיס:
Arthur (120 HP), strength 15, armor 8
Attack: 20הקוד שלך ייכתב בקבצים warrior.gd ו־knight.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
extends Node
func _ready():
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
var count := int(OS.read_string_from_stdin())
for i in count:
var p := OS.read_string_from_stdin().split(" ")
var c: Character
if p[0] == "knight":
c = Knight.new(p[1], int(p[2]), int(p[3]), int(p[4]))
elif p[0] == "warrior":
c = Warrior.new(p[1], int(p[2]), int(p[3]))
else:
c = Character.new(p[1], int(p[2]))
print(c.describe())
print("Attack: %d" % c.attack())
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידיםתרגלו בעצמכם: קומפיילר GDScript אונליין