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

دوال الـ Getters والـ Setters

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

عندما تكون أعضاء الفئة (class members) خاصة (private)، لا يمكن للكود الخارجي الوصول إليها مباشرة. تُعد الـ Getters والـ setters دوالاً عامة (public methods) توفر وصولاً متحكماً فيه لهذه الأعضاء الخاصة - حيث تقوم الـ getters بجلب القيم، بينما تقوم الـ setters بتعديلها.

class Temperature {
    double celsius;    // خاص - لا يمكن الوصول إليه مباشرة
    
public:
    // Getter - يعيد القيمة
    double getCelsius() const {
        return celsius;
    }
    
    // Setter - يقوم بتعديل القيمة مع التحقق من صحتها
    void setCelsius(double value) {
        if (value >= -273.15) {    // التحقق من الصفر المطلق
            celsius = value;
        }
    }
};

القوة الحقيقية لـ setters هي التحقق من الصحة.

بدلاً من السماح بتعيين أي قيمة، يمكنك فرض قواعد معينة. في المثال أعلاه، يتم رفض درجات الحرارة التي تقل عن الصفر المطلق. وبدون وجود دالة تعيين (setter)، يمكن لأي شخص تعيين بيانات غير صالحة مباشرةً.

يمكن للدوال الجالبة (Getters) أيضاً تحويل البيانات قبل إرجاعها:

class Temperature {
    double celsius;
public:
    double getCelsius() const { return celsius; }
    
    // دالة جالبة محسوبة - لا تخزن الفهرنهايت، بل تحسبه
    double getFahrenheit() const {
        return celsius * 9.0 / 5.0 + 32.0;
    }
    
    void setCelsius(double value) { celsius = value; }
};

لاحظ الكلمة المفتاحية const في دوال الجلب (getters) - فهذا يشير إلى أنها لا تعدل الكائن. لا يمكن أن تكون دوال التعيين (setters) ثابتة (const) لأن الغرض منها هو تغيير قيم الأعضاء. إن هذا النمط من استخدام دوال الجلب والتعيين أساسي لمبدأ التغليف (encapsulation)، مما يمنحك تحكماً كاملاً في كيفية الوصول إلى بيانات الفئة (class) وتعديلها.

challenge icon

التحدي

سهل

لنقم ببناء نظام ملف تعريف لاعب يوضح كيف توفر دوال الجلب (getters) ودوال التعيين (setters) وصولاً متحكماً فيه إلى البيانات الخاصة، بما في ذلك التحقق من الصحة والخصائص المحسوبة.

ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:

  • Player.h: قم بتعريف فئة Player تدير ملف تعريف شخصية اللعبة مع وصول محمي للبيانات. يجب أن تحتوي الفئة الخاصة بك على:
    • أعضاء خاصون (Private members): name (string)، و level (int)، و experience (int)
    • منشئ (Constructor) يأخذ اسماً ويقوم بتهيئة level إلى 1 و experience إلى 0
    • دالة جلب getName() تعيد اسم اللاعب
    • دالة جلب getLevel() تعيد المستوى الحالي
    • دالة جلب getExperience() تعيد نقاط الخبرة الحالية
    • دالة تعيين setName() تقبل فقط الأسماء التي لا تقل عن 3 أحرف — إذا كانت غير صالحة، احتفظ بالاسم الحالي دون تغيير
    • دالة تعيين addExperience(int points) تقبل فقط القيم الموجبة. عندما تصل الخبرة إلى 100 أو تتجاوزها، يرتفع مستوى اللاعب: قم بزيادة المستوى بمقدار 1 واطرح 100 من الخبرة. يمكن أن يحدث هذا عدة مرات إذا تمت إضافة خبرة كافية.
    • دالة جلب محسوبة getExperienceToNextLevel() تعيد عدد نقاط الخبرة الإضافية المطلوبة للوصول إلى المستوى التالي (دائماً 100 - current experience)

    قم بتمييز جميع دوال الجلب كـ const لأنها لا تعدل الكائن.

  • main.cpp: قم باستعراض دوال الجلب والتعيين الخاصة بك أثناء العمل. اقرأ اسم اللاعب ونقاط الخبرة المراد إضافتها من المدخلات (كل منهما في سطر منفصل)، ثم:

    • قم بإنشاء Player بالاسم المدخل
    • اطبع "Player: <name>, Level: <level>, XP: <experience>"
    • أضف نقاط الخبرة المدخلة باستخدام addExperience()
    • اطبع نفس سطر الحالة مرة أخرى لإظهار الحالة المحدثة
    • اطبع "XP to next level: <amount>"
    • حاول تغيير الاسم إلى "Al" (يجب أن يفشل التحقق من الصحة)
    • اطبع "Name after invalid change: <name>"
    • قم بتغيير الاسم إلى "Champion" (يجب أن ينجح)
    • اطبع "Name after valid change: <name>"

سيتم توفير مدخلات الخبرة كسلسلة نصية ستحتاج إلى تحويلها إلى عدد صحيح. قم بتضمين ملف الترويسة الخاص بك في main.cpp باستخدام #include "Player.h".

جرّب بنفسك

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

using namespace std;

int main() {
    // قراءة اسم اللاعب
    string playerName;
    getline(cin, playerName);

    // قراءة نقاط الخبرة المراد إضافتها (كسلسلة نصية، ثم تحويلها إلى int)
    string expString;
    getline(cin, expString);
    int expToAdd = stoi(expString);

    // TODO: إنشاء Player بالاسم المدخل

    // TODO: طباعة الحالة الأولية: "Player: <name>, Level: <level>, XP: <experience>"

    // TODO: إضافة نقاط الخبرة المدخلة باستخدام addExperience()

    // TODO: طباعة سطر الحالة المحدث

    // TODO: طباعة "XP to next level: <amount>"

    // TODO: محاولة تغيير الاسم إلى "Al" (يجب أن يفشل التحقق من الصحة)

    // TODO: طباعة "Name after invalid change: <name>"

    // TODO: تغيير الاسم إلى "Champion" (يجب أن ينجح)

    // TODO: طباعة "Name after valid change: <name>"

    return 0;
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming