التحقق من البيانات في الـ Setters
جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 20 من 61.
في الدرس السابق، أنشأنا دوال ضبط أساسية تُسنِد القيم ببساطة. لكن هذا يُغفل فائدة أساسية من التغليف: القدرة على حماية بياناتك من خلال إضافة منطق التحقق.
تخيّل Counter يجب ألا يصبح سالبًا أبدًا. من دون التغليف، يمكن لأي شخص كتابة c->value = -50 وإفساد الحالة. باستخدام دالة ضبط، تتحكّم في القيم المسموح بها:
// counter.c
void counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return; // رفض الإدخال غير الصالح بصمت
}
c->value = new_value;
}يتم الآن تجاهل القيم السالبة ببساطة.
قد تختار أيضًا إرجاع رمز حالة للإشارة إلى النجاح أو failure:
int counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return 0; // فشل
}
c->value = new_value;
return 1; // نجاح
}يتيح هذا النمط للمستدعي معرفة ما إذا كانت العملية قد نجحت. تتمثل الفكرة الأساسية في أن أدوات التعيين لا تقتصر على الإسناد؛ فهي حراس بوابة يفرضون قواعد بشأن ما يمكن أن تكون عليه حالة كائنك. هذه هي القوة الحقيقية للتغليف: يحافظ كائنك على سلامته الخاصة، بصرف النظر عما يحاول الكود الخارجي فعله.
التحدي
سهللنبنِ وحدة Temperature تحمي بياناتها باستخدام التحقق في أداة الضبط. ستنشئ متتبّعًا لدرجة الحرارة لا يقبل إلا القيم الواقعة ضمن نطاق صالح، موضحًا كيفية عمل أدوات الضبط كبوابات لحالة كائنك.
ستنشئ ثلاثة ملفات:
temperature.h: واجهتك العامة باستخدام نمط المؤشر المعتم. صرّح عن نوعTemperatureباستخدام تصريح forward فقط. صرّح عن هذه الدوال:create_temperature: تأخذ عددًا صحيحًا لدرجات initial وتعيد مؤشرًا إلى Temperaturefree_temperature: تحرر الذاكرة المخصّصةtemp_get_degrees: أداة getter تعيد قيمة درجة الحرارة الحاليةtemp_set_degrees: أداة setter تعيد قيمة من النوعint(1 عند النجاح، و0 عند الفشل)
TEMPERATURE_H.temperature.c: عرّف البنية الفعليةstruct Temperatureمع عضوint degreesمخفي. نفّذ جميع الدوال. النقطة الأساسية هي أداة setter. يجب ألا تقبل إلا القيم بين -50 و150 (بشكل inclusive). إذا كانت القيمة خارج هذا النطاق، فأعد 0 واترك درجة الحرارة دون تغيير. وإذا كانت صالحة، فحدّث القيمة وأعد 1.main.c: اعرض عملية التحقق من خلال محاولة ضبط درجات حرارة صالحة وغير صالحة، مع إظهار رفض القيم غير الصالحة وقبول القيم الصالحة.
ستتلقى ثلاث قيم input: درجة الحرارة initial، ودرجة حرارة صالحة لضبطها (ضمن النطاق)، ودرجة حرارة غير صالحة لمحاولة ضبطها (خارج النطاق).
في ملف main، أنشئ Temperature باستخدام القيمة initial واطبعها. ثم حاول ضبط درجة الحرارة غير الصالحة، وبما أنه ينبغي رفضها، اطبع النتيجة وأظهر أن القيمة بقيت دون تغيير. وأخيرًا، اضبط درجة الحرارة الصالحة، واطبع نتيجة النجاح، وأظهر القيمة المحدّثة. حرر الذاكرة وأكّد إتمام التنظيف.
اطبع الناتج بهذا التنسيق:
Initial: {degrees}
Set {invalid}: {0 or 1}
After invalid: {degrees}
Set {valid}: {0 or 1}
After valid: {degrees}
Freedعلى سبيل المثال، مع المدخلات 25 و100 و200، سيكون الناتج:
Initial: 25
Set 200: 0
After invalid: 25
Set 100: 1
After valid: 100
Freedيوضح هذا القوة الحقيقية للتغليف. تفرض أداة setter القواعد المتعلقة بما يشكّل درجة حرارة صالحة، فتحمي سلامة الكائن بغض النظر عن القيم التي يحاول الكود الخارجي إسنادها.
جرّب بنفسك
#include <stdio.h>
#include "temperature.h"
int main() {
// اقرأ المدخلات
int initial, valid_temp, invalid_temp;
scanf("%d", &initial);
scanf("%d", &valid_temp);
scanf("%d", &invalid_temp);
// TODO: أنشئ Temperature بالقيمة الأولية
// TODO: اطبع درجة الحرارة الأولية
// التنسيق: "Initial: {degrees}"
// TODO: حاول تعيين درجة الحرارة غير الصالحة
// اطبع النتيجة وأظهر أن القيمة تبقى دون تغيير
// التنسيق: "Set {invalid}: {0 or 1}"
// Format: "After invalid: {degrees}"
// TODO: عيّن درجة الحرارة الصالحة
// اطبع نتيجة النجاح وأظهر القيمة المحدّثة
// التنسيق: "Set {valid}: {0 or 1}"
// التنسيق: "After valid: {degrees}"
// TODO: حرّر الذاكرة واطبع "Freed"
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 عبر الإنترنت