مؤشر 'Self'
جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 7 من 61.
في اللغات كائنية التوجه مثل Python أو Java، عندما تستدعي object.method()، تمرر اللغة الكائن نفسه تلقائيًا إلى الطريقة. أما في C، فعلينا القيام بذلك يدويًا عبر تمرير مؤشر إلى البنية باعتباره الوسيط الأول.
يُسمّى هذا المؤشر تقليديًا self (مقتبسًا من Python) أو this (من C++). ويمنح function إمكانية الوصول إلى بيانات struct حتى تتمكن من قراءتها أو تعديلها:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
مؤشر self هو ما يجعل function تتصرف كأنها method. فهي تعرف أيّ player يجب تعديلها. ومن دونها، لن تكون لدى function أي وسيلة للوصول إلى مثيل struct المحدد. عند استدعاء هذه function، تمرّر عنوان struct الخاص بك:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health أصبح الآن 75
يُعد استخدام pointer (بدلاً من تمرير struct مباشرةً) أمرًا ضروريًا لإجراء التعديل. إذا مرّرت struct بالقيمة، فستتلقى function نسخةً منه، وستُفقد أي تغييرات عند عودة function. يضمن pointer استمرار التغييرات في struct الأصلي.
التحدي
سهللنبنِ وحدة Timer تتتبّع عدد seconds المنقضية. ستتدرّب على using نمط المؤشر "self" لتعديل الحالة الداخلية لـ struct من خلال functions تعمل كطرائق.
ستنشئ ثلاثة ملفات:
timer.h: Declare بنيةTimerذات member واحد من النوعint seconds. Declare أيضًا دالتين:timer_tick(takes مؤشرًا إلى Timer ويضيف عددًا محددًا من seconds) وtimer_reset(takes مؤشرًا إلى Timer ويعيد seconds إلى zero). استخدم include guards بالرمزTIMER_H.timer.c: Implement كلتا الدالتين. يجب أن تقبل دالةtimer_tickقيمةTimer *selfوint amount، ثم تضيف amount إلى seconds الخاص بالمؤقت. يجب أن تقبل دالةtimer_resetقيمةTimer *selfوتضبط seconds الخاص به على zero.main.c: أنشئ Timer، ونفّذ عمليات عليه، واعرض النتائج.
ستتلقى مُدخلين صحيحين: initial seconds للمؤقت وamount المراد إضافته عبر tick.
في ملفك الرئيسي:
- هيّئ
Timerبقيمة initial seconds - استدعِ
timer_tickلإضافة amount المحدد - اطبع seconds الحالية
- استدعِ
timer_resetلإعادة ضبط المؤقت - اطبع seconds مرة أخرى (should تكون 0)
اطبع النتائج بهذا التنسيق:
After tick: {seconds}
After reset: {seconds}على سبيل المثال، مع قيمة أولية قدرها 30 وإضافة 15 seconds، سيكون الناتج:
After tick: 45
After reset: 0جرّب بنفسك
#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;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
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مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكالتدرّب بنفسك: مترجم C عبر الإنترنت