Menu
CoddyTech
flag Ar iconالعربيةdown icon

تصميم الواجهات

جزء من قسم البرمجة كائنية التوجّه في رحلة 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 عبر الإنترنت