מחלקות ומתודות אבסטרקטיות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 23 מתוך 65.
יש מחלקות שקיימות רק כדי להרחיב אותן. לכל צורה יש שטח, אבל אי אפשר לחשב אותו עד שיודעים אם הצורה היא עיגול או מלבן. סמנו מחלקה כזאת ב-@abstract, בשורה שמעל class_name:
# shape.gd
@abstract
class_name Shape
extends RefCounted
@abstract func area() -> float
@abstract func perimeter() -> float
func describe() -> String:
return "Area %.1f, perimeter %.1f" % [area(), perimeter()]ל־@abstract func יש חתימה ואין גוף: אין נקודתיים ואין קוד אחריו. הוא מציין שכל מחלקת צאצא חייבת לספק את המתודה הזו. describe() היא מתודה רגילה; מחלקות צאצא יורשות אותה, והיא כבר יכולה לקרוא למתודות המופשטות.
אי אפשר ליצור אובייקט של מחלקה מופשטת. Shape.new() עוצר את התוכנית לפני שהיא מתחילה עם Parse Error: Cannot construct abstract class "Shape".
מחלקת בת שמממשת כל מתודה מופשטת היא מחלקה רגילה:
# rectangle.gd
class_name Rectangle
extends Shape
var width: float
var height: float
func _init(w: float, h: float) -> void:
width = w
height = h
func area() -> float:
return width * height
func perimeter() -> float:
return 2 * (width + height)var rect := Rectangle.new(4.0, 6.0)
print(rect.describe())Area 24.0, perimeter 20.0אם מחלקת־בת משמיטה אחת מהן, Godot מדווח על כך לפני ההרצה: Class "Square" must implement "Shape.perimeter()" and other inherited abstract methods or be marked as "@abstract". לכן לכל אובייקט שאפשר ליצור יש area() ו־perimeter().
למחלקה מופשטת עדיין יכולים להיות משתנים ו-_init(). מחלקות יורשות קוראות לו באמצעות super() כרגיל.
אתגר
קלחנות מקבלת שני אמצעי תשלום. לכל תשלום יש סכום וקבלה, אבל העמלה והשם תלויים באמצעי התשלום.
- הפוך את
PaymentMethodלמחלקה מופשטת והצהר על שתי מתודות מופשטות:fee() -> floatו-method_name() -> String. כתוב אתreceipt(), שמחזירהNAME: paid AMOUNT, fee FEE, total TOTALעם שתי ספרות אחרי הנקודה העשרונית עבור כל מספר (הסכום הכולל הוא הסכום בתוספת העמלה). CreditCard: העמלה היא 3% מהסכום (amount * 0.03), והשם הואCredit card.BankTransfer: העמלה היא1.5, או0.0כשהסכום הוא100או יותר, והשם הואBank transfer.
מחלקות הבת משתמשות בבנאי של PaymentMethod. הקוד שסופק קורא כמה תשלומים מופיעים בהמשך, ואז שורה אחת לכל תשלום: card AMOUNT או transfer AMOUNT. הוא מדפיס כל קבלה ואת סכום העמלות. עבור card 50 ו-transfer 120 הוא מדפיס:
Credit card: paid 50.00, fee 1.50, total 51.50
Bank transfer: paid 120.00, fee 0.00, total 120.00
Total fees: 1.50הקוד שלך נמצא בקבצים payment_method.gd, credit_card.gd ו-bank_transfer.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
extends Node
func _ready():
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
var count := int(OS.read_string_from_stdin())
var total_fees := 0.0
for i in count:
var p := OS.read_string_from_stdin().split(" ")
var payment: PaymentMethod
if p[0] == "card":
payment = CreditCard.new(float(p[1]))
else:
payment = BankTransfer.new(float(p[1]))
print(payment.receipt())
total_fees += payment.fee()
print("Total fees: %.2f" % total_fees)
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט4פולימורפיזם
חזרה על דריסת מתודותטיפוס ברווזמחלקות ומתודות אבסטרקטיותתכנון ממשקיםסיכום - מחשבון צורות2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידיםתרגלו בעצמכם: קומפיילר GDScript אונליין