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

مقدمة إلى الأساليب الافتراضية

جزء من قسم البرمجة كائنية التوجّه في رحلة GDScript على Coddy. الدرس 31 من 65.

تحتوي Python على طرائق سحرية مثل __init__ و__str__، وتستدعيها اللغة نيابةً عنك. والمكافئ في Godot هو الطريقة الافتراضية: طريقة لها اسم ثابت يبدأ بشرطة سفلية، وتعرّفها في صفك، ثم يستدعيها Godot في الوقت المناسب. لقد استخدمت اثنتين منها بالفعل:

  • تُنفَّذ _init() عندما تنشئ new() الكائن، مع الوسائط المُعطاة إلى new().
  • تُنفَّذ _ready() عندما تدخل عقدة إلى شجرة المشهد، وهي المكان الذي يبدأ فيه main.gd.

منها أيضًا _to_string()، التي تُستدعى عند طباعة كائن، وطرائق المكرّر التي تتيح لحلقة for المرور على كائن (وكلاهما في الدرسين التاليين)، و_notification()، التي تتلقى الأحداث من المحرّك. يصل أحدها، وهو NOTIFICATION_PREDELETE، قبل حذف الكائن مباشرةً:

# torch.gd
class_name Torch
extends RefCounted

var label: String

func _init(new_label: String = "Torch") -> void:
	label = new_label
	print(label, " lit")

func _notification(what: int) -> void:
	if what == NOTIFICATION_PREDELETE:
		print(label, " burned out")
# main.gd
var torch := Torch.new("Hall torch") # أُشعلت شعلة الممر
torch = null # انطفأت شعلة الممر

يُحذف كائن RefCounted بمجرد ألا يعود أي متغير يشير إليه، لذا فإن torch = null يرسل الإشعار فورًا. تجعل القيمة الافتراضية في _init() الوسيطة في new() اختيارية: ينشئ Torch.new() شعلةً تُسمى Torch.

تستخدم Python أيضًا أساليب سحرية للمعاملات، مثل __add__ للمعامل + و__eq__ للمعامل ==. لا تدعم GDScript التحميل الزائد للمعاملات: إن potion_a + potion_b خطأ. اكتب أسلوبًا بدلًا من ذلك:

# potion.gd
class_name Potion
extends RefCounted

var power: int

func _init(start_power: int) -> void:
	power = start_power

func combined(other: Potion) -> Potion:
	return Potion.new(power + other.power)

تعيد potion_a.combined(potion_b) جرعة جديدة وتترك الجرعتين الأصليتين دون تغيير. يتحقق == بين كائنين مما إذا كان الطرفان هما الكائن نفسه، وليس مما إذا كانت قيمتاهما متطابقتين: Potion.new(5) == Potion.new(5) تساوي false. اكتب طريقة مثل equals(other) عندما تحتاج إلى مقارنة القيم.

challenge icon

التحدي

سهل

اكتب الصنف Counter في counter.gd:

  • تحفظ _init(start = 0, step_size = 1) قيمة البداية في value وحجم الخطوة في step. القيم الافتراضية موجودة بالفعل في التوقيع، لذا تعمل جميع الاستدعاءات Counter.new() وCounter.new(5) وCounter.new(5, 2).
  • تضيف tick() قيمة step إلى value.
  • تحل plus(other) محل العامل +، الذي لا يتيح GDScript تعريفه: فهي تُرجع كائنًا جديدًا من Counter تكون قيمته مجموع القيمتين وخطوته هي خطوة هذا العداد. لا يتغير أي من العدادين.
  • تُرجع equals(other) القيمة true عندما تكون قيمة العدادين متساوية.

يقرأ الكود المرفق سطرين لإنشاء العدادين a وb (سطرًا فارغًا أو START أو START STEP)، ثم سطرًا واحدًا يحدد عدد مرات زيادة a وb خطوةً. ويطبع العدادين ومجموعهما، وما إذا كانت قيمتاهما متساويتين، وما إذا كان a == b. بالنسبة إلى الأسطر 5 و2 3 و3 1، يطبع:

a: 8 (step 1)
b: 5 (step 3)
a plus b: 13 (step 1)
same value: false
same object: false

ضع الكود في counter.gd. يحتوي main.gd على كود الإدخال/الإخراج المرفق ولا يمكن تعديله.

جرّب بنفسك

extends Node

func _ready():
	# كود الإدخال/الإخراج المقدَّم: اتركه كما هو
	var a := make_counter(OS.read_string_from_stdin())
	var b := make_counter(OS.read_string_from_stdin())
	var ticks := OS.read_string_from_stdin().split(" ")
	for i in int(ticks[0]):
		a.tick()
	for i in int(ticks[1]):
		b.tick()
	print("a: %d (step %d)" % [a.value, a.step])
	print("b: %d (step %d)" % [b.value, b.step])
	var total := a.plus(b)
	print("a plus b: %d (step %d)" % [total.value, total.step])
	print("same value: %s" % a.equals(b))
	print("same object: %s" % (a == b))

func make_counter(line: String) -> Counter:
	var parts := line.split(" ", false)
	if parts.is_empty():
		return Counter.new()
	if parts.size() == 1:
		return Counter.new(int(parts[0]))
	return Counter.new(int(parts[0]), int(parts[1]))
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجّه

تدرّب بنفسك: مترجم GDScript عبر الإنترنت