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

تعريف الـ Opaque Structs

جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 18 من 61.

الآن بعد أن فهمت مفهوم المؤشرات المعتمة، لِنَرَ كيفية إكمال النمط. يُصرّح ملف الترويسة بوجود نوع ما، لكن الملف المصدر هو المكان الذي تُعرِّف فيه ما يوجد بداخله فعليًا.

إليك الإعداد الكامل. أولًا، الترويسة التي تحتوي فقط على التصريح المسبق:

// counter.h
#ifndef COUNTER_H
#define COUNTER_H

typedef struct Counter Counter;  // نوع غير مكتمل

Counter *create_counter(int start);
void free_counter(Counter *c);

#endif

بعد ذلك، يحتوي الملف المصدر على تعريف البنية actual:

// counter.c
#include "counter.h"
#include <stdlib.h>

struct Counter {
    int value;      // مخفي من الخارج!
    int step;
};

Counter *create_counter(int start) {
    Counter *c = malloc(sizeof(Counter));
    c->value = start;
    c->step = 1;
    return c;
}

void free_counter(Counter *c) {
    free(c);
}

النقطة الأساسية: يظهر struct Counter { ... } فقط في ملف .c. أي ملف يتضمن counter.h يعرف أن Counter موجود، لكنه لا يستطيع رؤية value أو step. ستؤدي محاولة كتابة c->value في main.c إلى حدوث خطأ من المترجم: إن members غير مرئية حقًا.

يُعَدّ هذا الفصل أساس التغليف في C. والخطوة التالية هي توفير وصول مُتحكَّم فيه من خلال دوال getter وsetter.

challenge icon

التحدي

سهل

لنبنِ وحدة Timer توضّح نمط المؤشر المعتم. ستتدرّب على إخفاء تعريف البنية داخل الملف المصدر، مما يجعل أعضائها الداخلية غير مرئية تمامًا لأي كود يستخدم وحدتك.

ستنشىء ثلاثة ملفات:

  • timer.h: هذه هي الواجهة العامة الخاصة بك. Declare نوعًا معتمًا هو Timer باستخدام تصريح Forward فقط: لا تضع جسم البنية هنا! Declare أيضًا دالتين: create_timer (تأخذ عددًا صحيحًا لعدد الثواني وتعيد مؤشرًا إلى Timer) وfree_timer (تأخذ مؤشرًا إلى Timer وتنفّذ عملية التنظيف). استخدم حواجز include بالرمز TIMER_H.
  • timer.c: هنا يكمن الجزء السري. Define البنية الفعلية struct Timer بعضوين مخفيين: int seconds وint running (استخدم 1 للدلالة على running و0 للدلالة على stopped). Implement المُنشئ لتخصيص البنية، وInitialize seconds بالقيمة provided، واضبط running على 1. Implement المُدمّر لتحرير الذاكرة.
  • main.c: استخدم وحدة Timer الخاصة بك لإنشاء مؤقت والتأكد من أنه تم إنشاؤه بنجاح. بما أن أعضاء البنية مخفيون، لا يمكنك الوصول إليهم مباشرة. هذه هي الفكرة بالكامل! اطبع ببساطة رسالة تؤكد الإنشاء، ثم حرّر المؤقت واطبع رسالة تنظيف.

ستتلقى مُدخلًا واحدًا: عدد الثواني (عدد صحيح) الذي سيُستخدم لتهيئة المؤقت.

في ملفك الرئيسي، أنشئ مؤقتًا باستخدام قيمة الثواني provided. اطبع رسالة إنشاء، ثم حرّر المؤقت واطبع تأكيدًا.

اطبع الناتج بهذا التنسيق:

Timer created
Timer freed

الفكرة الأساسية هنا هي أن main.c يستطيع العمل مع مؤشرات Timer، لكنه لا يملك أي وسيلة للوصول إلى seconds أو running مباشرة. ستؤدي محاولة كتابة t->seconds في main.c إلى خطأ من المُصرّف، لأن جسم البنية مُعرَّف فقط في timer.c. هذا هو التغليف الحقيقي: تفاصيل Implement مخفية تمامًا عن مستخدمي وحدتك.

جرّب بنفسك

#include <stdio.h>
#include "timer.h"

int main() {
    int seconds;
    scanf("%d", &seconds);
    
    // TODO: أنشئ مؤقتًا بقيمة الثواني المُقدَّمة
    
    // TODO: Print "Timer created"
    
    // TODO: حرّر المؤقت
    
    // TODO: اطبع "Timer freed"
    
    return 0;
}
quiz iconاختبر نفسك

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

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

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