Menu
CoddyTech

תכנון ממשקים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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()

שמרו על כל ממשק קטן: כמה מתודות ששייכות לתפקיד אחד. מחלקה שמרחיבה אותו כותבת רק את המתודות שהיא צריכה.

challenge icon

אתגר

קל

בנו נגן מדיה סביב ממשק.

  • ב־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())
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר GDScript אונליין