مؤشر 'Self'
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 7 من 61.
في اللغات كائنية التوجه مثل Python أو Java، عندما تستدعي object.method()، تقوم اللغة تلقائيًا بتمرير الكائن نفسه إلى الـ method. أما في لغة C، فيجب علينا القيام بذلك يدويًا عن طريق تمرير pointer إلى الـ struct كمعامل أول.
يُسمى هذا المؤشر اصطلاحاً self (مستعار من Python) أو this (من C++). إنه يمنح الدالة إمكانية الوصول إلى بيانات الـ struct حتى تتمكن من قراءتها أو تعديلها:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
مؤشر self هو ما يجعل الدالة تعمل كميثود—فهو يعرف أي لاعب يجب تعديله. وبدونه، لن تملك الدالة أي وسيلة للوصول إلى مثيل الـ struct المحدد. عند استدعاء هذه الدالة، تقوم بتمرير عنوان الـ struct الخاص بك:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health أصبح الآن 75
يعد استخدام المؤشر (بدلاً من تمرير الـ struct مباشرة) أمراً ضرورياً للتعديل. إذا قمت بتمرير الـ struct بالقيمة، فستتلقى الدالة نسخة، وستُفقد أي تغييرات عند انتهاء الدالة. يضمن المؤشر استمرار التغييرات في الـ struct الأصلي.
التحدي
سهللنقم ببناء وحدة Timer تتبع الثواني المنقضية. ستتدرب على استخدام نمط مؤشر "self" لتعديل الحالة الداخلية لهيكل (struct) من خلال دوال تعمل كطرق (methods).
ستقوم بإنشاء ثلاثة ملفات:
timer.h: صرّح عن هيكلTimerيحتوي على عضو واحد من نوعint seconds. صرّح أيضاً عن دالتين:timer_tick(تأخذ مؤشراً إلى Timer وتضيف عدداً محدداً من الثواني) وtimer_reset(تأخذ مؤشراً إلى Timer وتضبط الثواني لتعود إلى الصفر). استخدم حراس التضمين (include guards) مع الرمزTIMER_H.timer.c: قم بتنفيذ كلتا الدالتين. يجب أن تقبل دالةtimer_tickمؤشراًTimer *selfوint amount، ثم تضيف القيمة (amount) إلى ثواني المؤقت. يجب أن تقبل دالةtimer_resetمؤشراًTimer *selfوتضبط ثوانيه على الصفر.main.c: أنشئ Timer، وقم بإجراء عمليات عليه، واعرض النتائج.
ستتلقى مدخلين من نوع عدد صحيح: الثواني الأولية للمؤقت و المقدار المراد إضافته عبر tick.
في ملفك الرئيسي:
- قم بتهيئة
Timerبقيمة الثواني الأولية. - استدعِ
timer_tickلإضافة المقدار المحدد. - اطبع الثواني الحالية.
- استدعِ
timer_resetلإعادة ضبط المؤقت. - اطبع الثواني مرة أخرى (يجب أن تكون 0).
اطبع النتائج بهذا التنسيق:
After tick: {seconds}
After reset: {seconds}على سبيل المثال، مع قيمة أولية 30 وإضافة 15 ثانية، سيكون الناتج:
After tick: 45
After reset: 0ورقة مرجعية
في لغة C، تحتاج الدوال التي تعمل على الهياكل (structs) إلى وصول صريح إلى مثيل الهيكل من خلال معلمة مؤشر (pointer parameter)، والتي تُسمى اصطلاحاً self أو this:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
يسمح المؤشر self للدالة بالوصول إلى بيانات الهيكل وتعديلها. عند استدعاء مثل هذه الدوال، قم بتمرير عنوان الهيكل الخاص بك:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health is now 75
يعد استخدام المؤشر أمراً ضرورياً للتعديل - فالتمرير بالقيمة سيؤدي إلى إنشاء نسخة، وستُفقد التغييرات عند انتهاء الدالة. يضمن المؤشر استمرار التغييرات في الهيكل الأصلي.
جرّب بنفسك
#include <stdio.h>
#include "timer.h"
int main() {
int initial_seconds, amount_to_add;
scanf("%d", &initial_seconds);
scanf("%d", &amount_to_add);
// TODO: قم بإنشاء Timer وتهيئته باستخدام initial_seconds
// TODO: استدعِ timer_tick لإضافة amount_to_add من الثواني
// TODO: اطبع الثواني الحالية بالتنسيق التالي: "After tick: {seconds}"
// TODO: استدعِ timer_reset لإعادة ضبط المؤقت
// TODO: اطبع الثواني مرة أخرى بالتنسيق التالي: "After reset: {seconds}"
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرة