الأصناف المختومة (Sealed Classes)
جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 22 من 70.
أحياناً قد ترغب في إيقاف سلسلة الوراثة. تمنع الكلمة المفتاحية sealed توريث الفئة، مما يؤدي إلى قفل تنفيذها بحيث لا يمكن لأي فئة أخرى توسيعها.
public sealed class FinalDog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}
// سيؤدي هذا إلى حدوث خطأ في التجميع (compile error):
// public class SuperDog : FinalDog { }لماذا قد تقوم بختم class؟ تُعد الأمان وسلامة التصميم من الأسباب الشائعة. فعندما تقوم بتصميم class بعناية ولا تريد لأي شخص تغيير سلوكها من خلال الوراثة، فإن ختمها يضمن بقاء التنفيذ الخاص بك كما هو.
يمكنك أيضاً منع إعادة تعريف (seal) دوال فردية بدلاً من الفئات بأكملها. هذا يمنع المزيد من التجاوز (overriding) مع الاستمرار في السماح بتوريث الفئة نفسها:
public class Dog : Animal
{
public sealed override void Speak()
{
Console.WriteLine("Woof!");
}
}
public class Puppy : Dog
{
// لا يمكن تجاوز Speak() - فهي مختومة (sealed)
// ولكن يمكن إضافة دوال جديدة
public void Whimper()
{
Console.WriteLine("Whimper...");
}
}لاحظ أن sealed على دالة (method) يجب أن تقترن بـ override. يمكنك فقط جعل الدالة sealed إذا كانت virtual بالفعل في فئة أب (parent class). يمنحك هذا تحكماً دقيقاً: السماح ببعض التخصيص في تسلسل الوراثة، ثم قفله عند نقطة معينة.
التحدي
سهللنقم ببناء نظام معالجة مدفوعات يوضح كيفية استخدام sealed لقفل التنفيذات الحرجة. ستقوم بإنشاء تسلسل هرمي حيث يمكن توسيع طرق دفع معينة، ولكن الطرق الأكثر أماناً تكون مختومة (sealed) لمنع أي تعديلات.
ستقوم بإنشاء أربعة ملفات لتنظيم الكود الخاص بك:
PaymentMethod.cs: قم بتعريف فئةPaymentMethodداخل مساحة الأسماءPayments. تحتوي هذه الفئة الأساسية على خاصيةName(string) ومنشئ (constructor) يقوم بتعيينها. قم بتضمين تابعvirtualيسمىProcessPayment(decimal amount)يعيد"Processing ${amount} via {Name}".CreditCardPayment.cs: قم بتعريف فئةCreditCardPaymentداخل مساحة الأسماءPaymentsوالتي ترث منPaymentMethod. أضف خاصيةCardNumber(string). يقبل المنشئ الاسم ورقم البطاقة، مع استخدامbaseلتمرير الاسم. قم بعملoverrideللتابعProcessPaymentباستخدام الكلمة المفتاحيةsealedبحيث لا يمكن لأي فئات مشتقة أخرى تغيير هذا السلوك. يجب أن يعيد"Charging ${amount} to card ending in {last 4 digits of CardNumber}".BankTransfer.cs: قم بتعريف فئةsealedتسمىBankTransferداخل مساحة الأسماءPaymentsترث منPaymentMethod. هذه الفئة بأكملها مختومة (sealed) - لا يمكن لأحد الوراثة منها. أضف خاصيةBankName(string). يقبل المنشئ الاسم واسم البنك. قم بعملoverrideللتابعProcessPaymentليعيد"Transferring ${amount} from {BankName}".Program.cs: في ملفك الرئيسي، قم بإنشاء مثيلات (instances) لجميع أنواع الدفع الثلاثة باستخدام قيم الإدخال. قم بتخزينها كمراجعPaymentMethodواستدعِProcessPaymentلكل منها لإظهار تعدد الأشكال (polymorphism) مع التنفيذات المختومة (sealed).
ستتلقى أربعة مدخلات:
- رقم بطاقة الائتمان (16 رقماً)
- اسم البنك
- مبلغ الدفع
اطبع نتيجة معالجة الدفع من خلال كل طريقة:
{base PaymentMethod result}
{CreditCardPayment result}
{BankTransfer result}على سبيل المثال، إذا كانت المدخلات هي 1234567890123456، و First National، و 150.00، فيجب أن يكون المخرج:
Processing $150.00 via Generic
Charging $150.00 to card ending in 3456
Transferring $150.00 from First Nationalاستخدم "Generic" كاسم لمثيل PaymentMethod الأساسي، و "Credit Card" لدفع بطاقة الائتمان، و "Bank Transfer" للتحويل البنكي.
يضمن التابع المختوم (sealed) في CreditCardPayment أنه إذا قام شخص ما بإنشاء فئة فرعية، فلن يتمكن من تغيير كيفية معالجة مدفوعات بطاقات الائتمان. تمنع الفئة المختومة BankTransfer أي وراثة على الإطلاق - كلاهما أنماط أمان مهمة في أنظمة الدفع!
ورقة مرجعية
تمنع الكلمة المفتاحية sealed وراثة الفئة (class) أو منع تجاوز (override) الدالة بشكل إضافي في سلسلة الوراثة.
ختم الفئة (Sealing a class):
public sealed class FinalDog : Animal
{
public override void Speak()
{
Console.WriteLine("Woof!");
}
}
// This would cause a compile error:
// public class SuperDog : FinalDog { }تُستخدم الفئات المختومة (Sealed classes) لأغراض الأمان وسلامة التصميم، مما يضمن عدم إمكانية تعديل التنفيذ من خلال الوراثة.
ختم الدالة (Sealing a method):
public class Dog : Animal
{
public sealed override void Speak()
{
Console.WriteLine("Woof!");
}
}
public class Puppy : Dog
{
// Cannot override Speak() - it's sealed
// But can add new methods
public void Whimper()
{
Console.WriteLine("Whimper...");
}
}يجب دمج الكلمة المفتاحية sealed في الدالة مع الكلمة override. يمكنك فقط ختم الدوال التي كانت بالفعل virtual في الفئة الأب. يتيح ذلك التخصيص حتى نقطة معينة في التسلسل الهرمي، ثم قفله بعد ذلك.
جرّب بنفسك
using System;
using Payments;
class Program
{
public static void Main(string[] args)
{
// قراءة المدخلات
string cardNumber = Console.ReadLine();
string bankName = Console.ReadLine();
decimal amount = Convert.ToDecimal(Console.ReadLine());
// TODO: باسم "Generic" و PaymentMethod قم بإنشاء مثيل أساسي من
// PaymentMethod قم بتخزينه كمرجع من نوع
// TODO: باسم "Credit Card" ورقم البطاقة CreditCardPayment قم بإنشاء مثيل من
// PaymentMethod قم بتخزينه كمرجع من نوع
// TODO: باسم "Bank Transfer" واسم البنك BankTransfer قم بإنشاء مثيل من
// PaymentMethod قم بتخزينه كمرجع من نوع
// TODO: لكل منها واطبع النتائج ProcessPayment قم باستدعاء
// يجب أن تكون كل نتيجة في سطر منفصل
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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