תכנון ממשקים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 24 מתוך 65.
ממשק הוא רשימה של מתודות שמחלקה מתחייבת לכלול, בלי קוד שמממש אותן. ל-Java ול-C# יש מילת מפתח בשם interface; ל-GDScript אין. יוצרים את אותו הדבר ממחלקה מופשטת שכל המתודות שלה מופשטות:
# drawable.gd
@abstract
class_name Drawable
extends RefCounted
@abstract func draw() -> String
@abstract func resize(factor: int) -> voidאין בו משתנים ואין בו גופי מתודות. הוא מתאר מה דבר שניתן לצייר יכול לעשות, וכל מחלקה מחליטה איך:
# banner.gd
class_name Banner
extends Drawable
var text: String
var size := 1
func _init(t: String) -> void:
text = t
func draw() -> String:
return "Banner '%s' at size %d" % [text, size]
func resize(factor: int) -> void:
size *= factorגם Circle יכול להרחיב את Drawable, עם radius משלו ועם draw() ו-resize() משלו. קוד שמשתמש בממשק תלוי רק בו, ולכן הוא עובד עם כל מחלקה שמרחיבה את Drawable, כולל מחלקות שנכתבו מאוחר יותר:
func render_all(items: Array[Drawable]) -> void:
for item in items:
item.resize(2)
print(item.draw())var items: Array[Drawable] = [Banner.new("Sale"), Circle.new(3)]
render_all(items)Banner 'Sale' at size 2
Circle with radius 6למחלקה יש הורה אחד, ולכן היא יכולה להרחיב ממשק אחד בלבד. כשמחלקה ממלאת תפקיד שני, כמו שמירה לקובץ, הרחב את הממשק הראשי ובדוק את התפקיד השני באמצעות has_method():
if item.has_method("save"):
item.save()שמרו על כל ממשק קטן: כמה מתודות ששייכות לתפקיד אחד. מחלקה שמרחיבה אותו כותבת רק את המתודות שהיא צריכה.
אתגר
קלבנו נגן מדיה סביב ממשק.
- ב־
playable.gd, הפכו אתPlayableלממשק: מחלקה מופשטת עם המתודות המופשטותplay() -> Stringו־duration() -> int(בשניות). Songיורשת מ־Playable.play()מחזירהPlaying song: TITLE by ARTIST, ו־duration()מחזירה את מספר השניות שלה.Videoיורשת מ־Playable.play()מחזירהPlaying video: TITLE in RESOLUTIONp(לדוגמה,in 1080p), ו־duration()מחזירה את מספר השניות שלה.Playlistמכירה רק אתPlayable.play_all()מדפיסה אתplay()של כל פריט, ו־total_time()מחזירה את משך הזמן הכולל בפורמטM:SS(שניות עם שתי ספרות, לדוגמה4:05).
הבנאים של Song ושל Video כבר כתובים. הקוד שסופק קורא כמה פריטים יופיעו, ואז שורה אחת לכל פריט: song TITLE ARTIST SECONDS או video TITLE RESOLUTION SECONDS. הוא קורא ל־play_all() ומדפיס את משך הזמן הכולל. עבור song Imagine Lennon 183 ו־video Trailer 1080 95 הוא מדפיס:
Playing song: Imagine by Lennon
Playing video: Trailer in 1080p
Total time: 4:38כתבו את הקוד שלכם בקבצים playable.gd, song.gd, video.gd ו־playlist.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
extends Node
func _ready():
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
var count := int(OS.read_string_from_stdin())
var playlist := Playlist.new()
for i in count:
var p := OS.read_string_from_stdin().split(" ")
if p[0] == "song":
playlist.add(Song.new(p[1], p[2], int(p[3])))
else:
playlist.add(Video.new(p[1], int(p[2]), int(p[3])))
playlist.play_all()
print("Total time: " + playlist.total_time())
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח selfמתודותמאפייניםבנאי (_init)חזרה – מחשבון פשוט4פולימורפיזם
חזרה על דריסת מתודותטיפוס ברווזמחלקות ומתודות אבסטרקטיותתכנון ממשקיםסיכום - מחשבון צורות2מאפייני מחלקה
משתני מופע לעומת משתנים סטטייםפונקציות סטטיותקובעי מאפייניםמאחזרי מאפייניםפרטיים לפי מוסכמהסיכום – מנהל חשבון בנק5כימוס
איברים ציבוריים ופרטייםאימות באמצעות Settersהסתרת מידעמאפיינים לקריאה בלבדסיכום – מערכת לניהול רשומות תלמידיםתרגלו בעצמכם: קומפיילר GDScript אונליין