Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

مؤشر '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 الأصلي.

challenge icon

التحدي

سهل

لنقم ببناء وحدة 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.

في ملفك الرئيسي:

  1. قم بتهيئة Timer بقيمة الثواني الأولية.
  2. استدعِ timer_tick لإضافة المقدار المحدد.
  3. اطبع الثواني الحالية.
  4. استدعِ timer_reset لإعادة ضبط المؤقت.
  5. اطبع الثواني مرة أخرى (يجب أن تكون 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;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming