تنفيذ إخفاء البيانات
جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 33 من 70.
يتجاوز إخفاء البيانات مجرد استخدام حقول private. يتعلق الأمر بتصميم فئتك بحيث تكون تفاصيل التنفيذ الداخلية غير مرئية تمامًا للكود الخارجي، مع الكشف فقط عما هو ضروري من خلال واجهة عامة نظيفة.
فكر في فئة (class) تتتبع كلمة مرور المستخدم. أنت لا تريد أن يتمكن أي شخص من الوصول إلى كلمة المرور الخام - ولا حتى لقراءتها:
public class UserAccount
{
private string passwordHash;
public void SetPassword(string password)
{
passwordHash = HashPassword(password);
}
public bool VerifyPassword(string password)
{
return HashPassword(password) == passwordHash;
}
private string HashPassword(string password)
{
return password.GetHashCode().ToString();
}
}لاحظ أنه لا توجد طريقة لاسترداد كلمة المرور أو حتى الهاش (hash). يمكن للكود الخارجي فقط تعيين كلمة مرور أو التحقق منها - فآلية التخزين الداخلية مخفية تماماً. كما أن طريقة HashPassword هي أيضاً خاصة (private) لأنها من تفاصيل التنفيذ التي قد تتغير دون التأثير على كيفية استخدام الفئة (class).
يحمي هذا النهج الـ class الخاص بك من سوء الاستخدام ويمنحك الحرية لتغيير الأجزاء الداخلية لاحقاً. إذا قررت استخدام hashing algorithm مختلفة، فلن يتوقف أي كود خارجي عن العمل لأن لا شيء يعتمد على كيفية تخزين كلمة المرور.
التحدي
سهللنقم ببناء نظام محفظة آمن يوضح المفهوم الحقيقي لإخفاء البيانات (data hiding). ستقوم بإنشاء محفظة رقمية حيث يكون الرصيد محميًا تمامًا من الوصول المباشر - يمكن للكود الخارجي فقط الإيداع، السحب، والتحقق مما إذا كانت المعاملات ممكنة، ولكن لا يمكنه أبدًا رؤية أو التلاعب بالرصيد الفعلي مباشرة.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
Wallet.cs: أنشئ فئةWalletداخل مساحة الأسماءFinanceالتي تحافظ على رصيدها مخفيًا تمامًا. يجب أن تحتوي المحفظة على:- حقل خاص (private field) لتخزين الرصيد (decimal)
- طريقة خاصة (private method) باسم
FormatBalance()تعيد الرصيد منسقًا كسلسلة نصية للعملة مثل"$123.45"- هذه أداة مساعدة داخلية لا ينبغي كشفها للخارج - طريقة عامة (public method) باسم
Deposit(decimal amount)تضيف إلى الرصيد فقط إذا كان المبلغ موجبًا، وتعيدtrueإذا نجحت العملية، وfalseخلاف ذلك - طريقة عامة (public method) باسم
Withdraw(decimal amount)تطرح من الرصيد فقط إذا كان المبلغ موجبًا ولا يتجاوز الرصيد الحالي، وتعيدtrueإذا نجحت العملية، وfalseخلاف ذلك - طريقة عامة (public method) باسم
CanAfford(decimal amount)تعيدtrueإذا كان الرصيد أكبر من أو يساوي المبلغ، وfalseخلاف ذلك - طريقة عامة (public method) باسم
GetStatement()تستخدم الطريقة الخاصةFormatBalance()داخليًا وتعيد"Current balance: {formatted balance}"
Program.cs: في ملفك الرئيسي، أنشئ كائنًا منWalletوقم بإجراء سلسلة من المعاملات باستخدام قيم الإدخال. أظهر كيف تحمي المحفظة حالتها الداخلية بينما لا تزال توفر وظائف مفيدة من خلال واجهتها العامة.
ستتلقى ثلاثة مدخلات:
- مبلغ الإيداع الأولي (decimal)
- مبلغ السحب المراد محاولته (decimal)
- المبلغ المراد التحقق من القدرة على تحمله (decimal)
اطبع المخرجات بهذا التنسيق:
Deposit {amount}: {True/False}
{GetStatement() result}
Withdraw {amount}: {True/False}
{GetStatement() result}
Can afford {amount}: {True/False}على سبيل المثال، إذا كانت المدخلات هي 100.50، 30.25، و 80.00، يجب أن تكون المخرجات:
Deposit 100.50: True
Current balance: $100.50
Withdraw 30.25: True
Current balance: $70.25
Can afford 80.00: Falseالفكرة الجوهرية هنا هي أن الكود الخارجي لا يلمس حقل الرصيد مباشرة أبدًا. حتى سلسلة الرصيد المنسقة تأتي من خلال طريقة عامة تستخدم داخليًا أداة مساعدة خاصة. هذا هو إخفاء البيانات - تفاصيل التنفيذ غير مرئية تمامًا، وأنت حر في تغيير كيفية تخزين الرصيد أو تنسيقه دون كسر أي كود يستخدم محفظتك!
ورقة مرجعية
إخفاء البيانات يعني تصميم الفئات بحيث تكون تفاصيل التنفيذ الداخلية غير مرئية تمامًا للكود الخارجي، مع كشف ما هو ضروري فقط من خلال واجهة عامة نظيفة.
استخدم الحقول private لتخزين البيانات الحساسة وتوفير وصول محكوم من خلال الأساليب public:
public class UserAccount
{
private string passwordHash;
public void SetPassword(string password)
{
passwordHash = HashPassword(password);
}
public bool VerifyPassword(string password)
{
return HashPassword(password) == passwordHash;
}
private string HashPassword(string password)
{
return password.GetHashCode().ToString();
}
}المبادئ الأساسية:
- لا يوجد وصول مباشر للبيانات الداخلية (لا توجد دوال جلب للحقول الحساسة)
- أساليب مساعدة خاصة (Private) لتفاصيل التنفيذ
- توفر الأساليب العامة (Public) عمليات محكومة فقط
- آلية التخزين الداخلية مخفية تمامًا
يحمي هذا الفئة من سوء الاستخدام ويسمح بتغيير التنفيذ الداخلي دون كسر الكود الخارجي.
جرّب بنفسك
using System;
using Finance;
class Program
{
public static void Main(string[] args)
{
// قراءة قيم المدخلات
decimal depositAmount = Convert.ToDecimal(Console.ReadLine());
decimal withdrawAmount = Convert.ToDecimal(Console.ReadLine());
decimal checkAmount = Convert.ToDecimal(Console.ReadLine());
// TODO: إنشاء مثيل من Wallet
// TODO: إجراء عملية الإيداع وطباعة النتيجة بالتنسيق: "Deposit {amount}: {True/False}"
// TODO: طباعة كشف الحساب باستخدام GetStatement()
// TODO: إجراء عملية السحب وطباعة النتيجة بالتنسيق: "Withdraw {amount}: {True/False}"
// TODO: طباعة كشف الحساب باستخدام GetStatement()
// TODO: التحقق من القدرة على تحمل التكلفة وطباعة النتيجة بالتنسيق: "Can afford {amount}: {True/False}"
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات OOP
الملفات الخارجيةNamespaces والتوجيهاتمقدمة في Classes و Objectsالكلمة المفتاحية 'this'Methods والمعاملاتFields مقابل PropertiesConstructorsObject Initializersمراجعة - آلة حاسبة بسيطة4الوراثة
صيغة الوراثة الأساسية (:)الكلمة المفتاحية 'base'الكلمات المفتاحية Virtual و Overrideالأصناف المختومة (Sealed Classes)الفئة الأساسية 'object'مراجعة - هيكلية الموظفين7ميزات متقدمة
تحميل العوامل (Operator Overloading)المفهرسات (Indexers (this[]))إعادة تعريف ()ToStringدوال التوسعة (Extension Methods)ملخص - Custom List2الخصائص والأعضاء الساكنة (Static Members)
الخصائص المطبقة تلقائيًا (Auto-Implemented Properties)خصائص القراءة فقط والكتابة فقطالحقول والدوال الساكنة (Static)الفئات الساكنة (Static Classes)الأعضاء ذات البنية التعبيرية (Expression-Bodied Members)5تعدد الأشكال والواجهات (Polymorphism & Interfaces)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالواجهة مقابل الفئة المجردة (Abstract Class)الواجهات المتعددةالواجهات الصريحةUpcasting و Downcastingملخص - حاسبة الأشكال8مفاهيم البرمجة كائنية التوجه (OOP) المتقدمة
التركيب بدلاً من الوراثةالـ Generics (الأصناف والدوال)الـ Delegates والأحداثالـ Attributes والـ Reflectionواجهة IDisposable وجملة usingأساسيات Dependency Injection