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

مستويات الوصول في الوراثة

جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 49 من 104.

يؤثر نوع الوراثة الذي تختاره على كيفية الوصول إلى أعضاء الفئة الأساسية (base class) في الفئة المشتقة (derived class). توفر لغة C++ ثلاثة خيارات: الوراثة من النوع public، و protected، و private.

إليك كيف يغير كل نوع من أنواع الوراثة إمكانية الوصول إلى الأعضاء:

عضو القاعدة (Base Member)الوراثة العامة (public inheritance)الوراثة المحمية (protected inheritance)الوراثة الخاصة (private inheritance)
publicpublicprotectedprivate
protectedprotectedprotectedprivate
privateغير قابل للوصول (inaccessible)غير قابل للوصول (inaccessible)غير قابل للوصول (inaccessible)
class Base {
public:
    int pub;
protected:
    int prot;
private:
    int priv;
};

class PublicDerived : public Base {
    // pub عام (public)، و prot محمي (protected)، و priv لا يمكن الوصول إليه
};

class ProtectedDerived : protected Base {
    // pub محمي (protected)، و prot محمي (protected)، و priv لا يمكن الوصول إليه
};

class PrivateDerived : private Base {
    // pub خاص (private)، و prot خاص (private)، و priv لا يمكن الوصول إليه
};

الوراثة العامة تجسد علاقات "is-a" وهي الأكثر شيوعاً على الإطلاق. فالـ Dog هو Animal، لذا يمكن للكود الخارجي التعامل معه على هذا الأساس.

تمثل الوراثة المحمية والخاصة علاقات "مُنفذ بدلالة" (implemented-in-terms-of). فهي تخفي واجهة الفئة الأساسية عن الكود الخارجي، وهو أمر مفيد عندما تريد إعادة استخدام التنفيذ دون الكشف عن علاقة الوراثة. ومع الوراثة الخاصة، تفقد حتى الفئات المشتقة اللاحقة إمكانية الوصول إلى أعضاء الفئة الأساسية الأصلية.

challenge icon

التحدي

سهل

دعنا نستكشف كيف تؤثر أنواع الوراثة المختلفة على إمكانية الوصول إلى الأعضاء من خلال بناء تسلسل هرمي بسيط للأجهزة. ستقوم بإنشاء فئة أساسية Device وثلاث فئات مشتقة، كل منها يستخدم نوع وراثة مختلف، لترى بنفسك كيف تقوم الوراثة العامة (public)، والمحمية (protected)، والخاصة (private) بتحويل الوصول إلى الأعضاء.

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • Device.h: قم بتعريف فئة أساسية Device مع ثلاثة أعضاء بمستويات وصول مختلفة:
    • عضو عام (public) من نوع std::string model
    • عضو محمي (protected) من نوع int serialNumber
    • عضو خاص (private) من نوع int internalCode (يتم ضبطه على 999 افتراضياً)
    • دالة عامة (public method) باسم showModel() تقوم بطباعة: Model: <model>

    ثم قم بإنشاء ثلاث فئات مشتقة ترث كل منها من Device باستخدام أنواع وراثة مختلفة:

    • PublicDevice باستخدام الوراثة العامة (public inheritance) — أضف دالة displaySerial() تقوم بطباعة: Serial: <serialNumber>
    • ProtectedDevice باستخدام الوراثة المحمية (protected inheritance) — أضف دالة displaySerial() تقوم بطباعة: Serial: <serialNumber>
    • PrivateDevice باستخدام الوراثة الخاصة (private inheritance) — أضف دالة displaySerial() تقوم بطباعة: Serial: <serialNumber>

    يجب أن تحتوي كل فئة مشتقة على منشئ (constructor) يأخذ اسم الطراز (model name) والرقم التسلسلي (serial number)، ويمرر الطراز إلى الفئة الأساسية ويقوم بضبط الرقم التسلسلي.

  • main.cpp: اقرأ مدخلين (كل منهما في سطر منفصل):
    1. اسم الطراز (string)
    2. الرقم التسلسلي (integer)

    قم بإنشاء كائن واحد من كل نوع مشتق بنفس قيم المدخلات. ثم وضح اختلافات الوصول:

    بالنسبة لـ PublicDevice:

    • استدعِ showModel() مباشرة على الكائن (يعمل لأن الوراثة العامة تبقيها عامة)
    • الوصول إلى model مباشرة واطبع: Direct model access: <model>
    • استدعِ displaySerial()

    بالنسبة لـ ProtectedDevice و PrivateDevice:

    • استدعِ فقط displaySerial() (حيث أن showModel() و model الموروثين لم يعد من الممكن الوصول إليهما علناً من الخارج)

    تنسيق المخرجات:

    --- PublicDevice ---
    Model: <model>
    Direct model access: <model>
    Serial: <serial>
    --- ProtectedDevice ---
    Serial: <serial>
    --- PrivateDevice ---
    Serial: <serial>

على سبيل المثال، مع المدخلات Laptop و 12345:

--- PublicDevice ---
Model: Laptop
Direct model access: Laptop
Serial: 12345
--- ProtectedDevice ---
Serial: 12345
--- PrivateDevice ---
Serial: 12345

لاحظ كيف يسمح PublicDevice فقط بالوصول الخارجي إلى الأعضاء العامة الموروثة. تخفي أنواع الوراثة الأخرى واجهة الفئة الأساسية عن الكود الخارجي، ولكن لا يزال بإمكان الفئات المشتقة الوصول إلى الأعضاء المحمية داخلياً من خلال دوالها الخاصة.

ورقة مرجعية

تقدم لغة C++ ثلاثة أنواع من الوراثة التي تتحكم في كيفية الوصول إلى أعضاء الفئة الأساسية (base class) في الفئات المشتقة (derived classes):

عضو الفئة الأساسيةالوراثة العامة (public)الوراثة المحمية (protected)الوراثة الخاصة (private)
publicpublicprotectedprivate
protectedprotectedprotectedprivate
privateلا يمكن الوصول إليهلا يمكن الوصول إليهلا يمكن الوصول إليه
class Base {
public:
    int pub;
protected:
    int prot;
private:
    int priv;
};

class PublicDerived : public Base {
    // pub هو public، و prot هو protected، و priv لا يمكن الوصول إليه
};

class ProtectedDerived : protected Base {
    // pub هو protected، و prot هو protected، و priv لا يمكن الوصول إليه
};

class PrivateDerived : private Base {
    // pub هو private، و prot هو private، و priv لا يمكن الوصول إليه
};

تمثل الوراثة العامة (Public inheritance) علاقة "هو-نوع-من" (is-a) وهي الأكثر شيوعاً. يمكن للكود الخارجي الوصول إلى الأعضاء العامة للفئة الأساسية من خلال الفئة المشتقة.

تمثل الوراثة المحمية والخاصة (Protected and private inheritance) علاقة "مُنفذ-بدلالة" (implemented-in-terms-of). فهي تخفي واجهة الفئة الأساسية عن الكود الخارجي. ومع الوراثة الخاصة، تفقد حتى الفئات المشتقة اللاحقة القدرة على الوصول إلى أعضاء الفئة الأساسية الأصلية.

جرّب بنفسك

#include <iostream>
#include <string>
#include "Device.h"

using namespace std;

int main() {
    // قراءة المدخلات
    string modelName;
    int serialNum;
    
    getline(cin, modelName);
    cin >> serialNum;
    
    // TODO: إنشاء كائنات من كل نوع مشتق باستخدام قيم المدخلات
    // PublicDevice pubDev(modelName, serialNum);
    // ProtectedDevice protDev(modelName, serialNum);
    // PrivateDevice privDev(modelName, serialNum);
    
    // TODO: توضيح الوصول إلى PublicDevice
    cout << "--- PublicDevice ---" << endl;
    // - استدعاء showModel() مباشرة على الكائن
    // - الوصول إلى model مباشرة وطباعة: Direct model access: <model>
    // - استدعاء displaySerial()
    
    // TODO: توضيح الوصول إلى ProtectedDevice
    cout << "--- ProtectedDevice ---" << endl;
    // - استدعاء displaySerial() فقط (لا يمكن الوصول إلى showModel و model بشكل عام)
    
    // TODO: توضيح الوصول إلى PrivateDevice
    cout << "--- PrivateDevice ---" << endl;
    // - استدعاء displaySerial() فقط (لا يمكن الوصول إلى showModel و model بشكل عام)
    
    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming