ثابت الفئة
في برمجة الحاسوب ، وتحديدًا البرمجة كائنية التوجه ، يُعدّ ثابت الفئة (أو ثابت النوع ) ثابتًا يُستخدم لتقييد كائنات الفئة . يجب أن تحافظ توابع الفئة على هذا الثابت. يُقيّد ثابت الفئة الحالة المخزنة في الكائن.
تُحدد ثوابت الفئة أثناء عملية الإنشاء وتُحافظ عليها باستمرار بين استدعاءات الدوال العامة. قد يُخالف الكود داخل الدوال هذه الثوابت طالما تُستعاد قبل انتهاء الدالة العامة. في حالة التزامن ، يتطلب الحفاظ على الثابت في الدوال عادةً إنشاء قسم حرج عن طريق قفل الحالة باستخدام قفل تبادلي (mutex) .
الثابت الكائني ، أو الثابت التمثيلي ، هو بنية برمجية حاسوبية تتألف من مجموعة من الخصائص الثابتة التي تبقى دون تغيير بغض النظر عن حالة الكائن. يضمن هذا أن الكائن سيلبي دائمًا الشروط المحددة مسبقًا، وبالتالي يمكن للأساليب، بالتالي، الإشارة إلى الكائن دائمًا دون خطر وضع افتراضات غير دقيقة. يساعد تعريف الثوابت الفئوية المبرمجين والمختبرين على اكتشاف المزيد من الأخطاء أثناء اختبار البرمجيات .
ثوابت الفئات والوراثة
يتعزز الأثر المفيد لثوابت الأصناف في البرمجيات الموجهة للكائنات في وجود الوراثة. تُورَث ثوابت الأصناف، أي أن "ثوابت جميع الأصناف الأصلية للصنف تنطبق على الصنف نفسه". [ 1 ]
تسمح الوراثة للفئات الفرعية بتغيير بيانات تنفيذ الفئات الأصلية، مما قد يُتيح للفئة الفرعية تغيير حالة النسخ بطريقة تجعلها غير صالحة من وجهة نظر الفئة الأصلية. ويُعدّ القلق من هذا النوع من سلوك الفئات الفرعية غير المرغوب فيه أحد الأسباب التي يُقدّمها مصممو البرمجيات الكائنية التوجه لتفضيل التركيب على الوراثة (أي أن الوراثة تُخلّ بمبدأ التغليف). [ 2 ]
مع ذلك، ولأن ثوابت الأصناف تُورَث، فإن ثابت الصنف لأي صنف معين يتألف من جميع تأكيدات الثوابت المكتوبة مباشرةً على ذلك الصنف، بالإضافة إلى جميع بنود الثوابت الموروثة من الأصناف الأصلية. هذا يعني أنه حتى لو كان بإمكان الأصناف الفرعية الوصول إلى بيانات التنفيذ الخاصة بأصنافها الأصلية، فإن ثابت الصنف يمنعها من التلاعب بتلك البيانات بأي شكل من الأشكال التي تُنتج نسخة غير صالحة أثناء التشغيل.
دعم لغات البرمجة
التأكيدات
تدعم لغات البرمجة الشائعة مثل بايثون [ 3 ] ، وبي إتش بي [ 4 ] ، وجافا سكريبت [ 5 ] ، وسي++، وجافا، التأكيدات افتراضيًا، والتي يمكن استخدامها لتعريف ثوابت الأصناف. يتمثل أحد الأنماط الشائعة لتطبيق الثوابت في الأصناف في أن يقوم مُنشئ الصنف برمي استثناء إذا لم يتحقق الثابت. بالنسبة للأصناف القابلة للتغيير، على سبيل المثال، في وجود دوال التعيين أو عندما تعتمد على كائنات أخرى قابلة للتغيير، قد يرغب المرء أيضًا في التحقق بعد كل تعديل مما إذا تم إعادة إنشاء الثابت بشكل صحيح، مما يضمن أن تطبيقات الدوال تحافظ بالفعل على ثوابت الصنف.
الدعم الأصلي
يُعدّ ثبات الفئة عنصرًا أساسيًا في التصميم التعاقدي . لذا، فإن لغات البرمجة التي توفر دعمًا أصليًا كاملًا للتصميم التعاقدي، مثل إيفل وآدا ودافني ودي ، ستوفر أيضًا دعمًا كاملًا لثبات الفئة .
دعم غير أصلي
بالنسبة للغة C++ ، توفر مكتبة Loki إطار عمل للتحقق من ثوابت الفئة، وثوابت البيانات الثابتة، وسلامة الاستثناءات.
بالنسبة للغة جافا، هناك أداة أكثر قوة تسمى لغة نمذجة جافا والتي توفر طريقة أكثر قوة لتحديد ثوابت الفئة.
أمثلة
الدعم الأصلي
آدا
تدعم لغة البرمجة Ada بشكلٍ أصيل ثوابت النوع (بالإضافة إلى الشروط المسبقة واللاحقة، ومسندات الأنواع الفرعية، وما إلى ذلك). يمكن تحديد ثابت النوع على نوع خاص (على سبيل المثال، لتحديد علاقة بين خصائصه المجردة)، أو على تعريفه الكامل (عادةً للمساعدة في التحقق من صحة تنفيذ النوع). [ 6 ] فيما يلي مثال على ثابت نوع مُحدد على التعريف الكامل لنوع خاص يُستخدم لتمثيل مكدس منطقي. يستخدم التنفيذ مصفوفة، ويحدد ثابت النوع خصائص معينة للتنفيذ تُمكّن من إثبات السلامة. في هذه الحالة، يضمن الثابت أنه بالنسبة لمكدس ذي عمق منطقي N، فإن أول N عنصر من المصفوفة هي قيم صالحة. يضمن الشرط الابتدائي الافتراضي لنوع Stack، من خلال تحديد مكدس فارغ، صحة الثابت في البداية، ويحافظ Push على الثابت. تُمكّن صحة الشرط الثابت دالة Pop من الاعتماد على حقيقة أن أعلى المكدس قيمة صالحة، وهو ما يلزم لإثبات شرط ما بعد التنفيذ لدالة Pop. يُمكّن شرط ثابت أكثر تعقيدًا من إثبات صحة الوظيفة بالكامل، مثل أن دالة Pop تُعيد القيمة المُمرّرة إلى دالة Push المقابلة، ولكن في هذه الحالة نحاول فقط إثبات أن دالة Pop لا تُعيد قيمة غير صالحة (Invalid_Value).
النوع العام Item خاص ؛ Invalid_Value : في Item ؛ الحزمة Stacks هي نوع Stack ( العمق الأقصى : موجب ) خاص مع Default_Initial_Condition = > Is_Empty ( Stack ) ؛دالة Is_Empty ( S : في Stack ) تُرجع قيمة منطقية ؛ دالة Is_Full ( S : في Stack ) تُرجع قيمة منطقية .إجراء Push ( S : إدخال/ إخراج Stack ؛ I : إدخال Item ) مع Pre => not Is_Full ( S ) ثم I /= Invalid_Value ، Post => not Is_Empty ( S )؛ إجراء Pop ( S : إدخال/إخراج Stack ؛ I : إخراج Item ) مع Pre = > not Is_Empty ( S )، Post => not Is_Full ( S ) ثم I /= Invalid_Value ؛ نوع Item_Array خاص هو مصفوفة ( نطاق موجب <>) من Item ؛نوع Stack ( العمق الأقصى : موجب ) هو سجل طوله : طبيعي := 0 ؛ بياناته : مصفوفة عناصر ( 1 .. العمق الأقصى ) := ( الآخرون => قيمة غير صالحة )؛ نهاية السجل مع نوع ثابت => الطول <= العمق الأقصى، ثم ( لكل J في 1 .. الطول = > بيانات ( J ) / = قيمة غير صالحة )؛دالة Is_Empty ( S : في Stack ) تُرجع قيمة منطقية is ( S.Length = 0 ) ؛ دالة Is_Full ( S : في Stack ) تُرجع قيمة منطقية is ( S.Length = S.Max_Depth ) ؛ نهاية Stacks ؛د
تدعم لغة البرمجة D بشكلٍ أصلي ثوابت الفئات، بالإضافة إلى تقنيات البرمجة التعاقدية الأخرى . إليك مثال من الوثائق الرسمية. [ 7 ]
class Date { int day ; int hour ;invariant () { assert ( day >= 1 && day <= 31 ); assert ( hour >= 0 && hour <= 23 ); } }إيفل
في لغة إيفل ، يظهر الثابت الخاص بالفئة في نهاية الفئة بعد الكلمة المفتاحية invariant.
تاريخ الحصةاصنعالميزة { لا شيء } -- التهيئةإنشاء ( a_day : عدد صحيح ; a_hour : عدد صحيح ) -- تهيئة `Current` باستخدام `a_day` و`a_hour`. يتطلب valid_day : a_day >= 1 و a_day <= 31 valid_hour : a_hour >= 0 و a_hour <= 23 do day := a_day hour := a_hour ensure day_set : day = a_day hour_set : hour = a_hour endميزة -- الوصولاليوم : عدد صحيح -- يوم الشهر لـ "الحالي"الساعة : عدد صحيح -- ساعة اليوم لـ "الحالي"ميزة -- تغيير العنصرset_day ( a_day : INTEGER ) -- تعيين قيمة `day` إلى `a_day` يتطلب valid_argument : a_day >= 1 و a_day <= 31 do day := a_day ensure day_set : day = a_day endset_hour ( a_hour : INTEGER ) -- تعيين قيمة `hour` إلى `a_hour` يتطلب valid_argument : a_hour >= 0 و a_hour <= 23 do hour := a_hour ensure hour_set : hour = a_hour endثابت valid_day : اليوم >= 1 واليوم <= 31 ، ثابت valid_hour : الساعة >= 0 والساعة <= 23 نهايةدعم غير أصلي
لغة سي++
توفر مكتبة Loki (C++) إطار عمل كتبه ريتشارد سبوساتو للتحقق من ثوابت الفئة، وثوابت البيانات الثابتة، ومستوى أمان الاستثناءات .
هذا مثالٌ على كيفية استخدام فئةٍ ما لـ Loki::Checker للتحقق من بقاء الثوابت صحيحةً بعد تغيير كائنٍ ما. يستخدم المثال كائن نقطة جغرافية لتخزين موقعٍ على سطح الأرض كإحداثياتٍ لخط العرض وخط الطول.
الثوابت الجغرافية هي:
- لا يجوز أن يتجاوز خط العرض 90 درجة شمالاً.
- لا يجوز أن يقل خط العرض عن -90 درجة جنوباً.
- لا يجوز أن يتجاوز خط الطول 180 درجة شرقاً.
- لا يجوز أن يكون خط الطول أقل من -180 درجة غرباً.
استيراد <cassert> ؛ استيراد < loki / Checker.h > ؛تصدير الوحدة النمطية ويكيبيديا . أمثلة . نقطة جغرافية ؛استيراد wikipedia.examples.Degrees ؛باستخدام ويكيبيديا :: أمثلة :: درجات ؛/** * مطلوب للتحقق من ثوابت الفئة. * @note تقوم الدالة CheckFor بفحص صحة العديد من الدوال لتحديد * ما إذا كان الكود قد انتهك أيًا من الثوابت، أو ما إذا كان أي محتوى قد تغير، أو ما إذا * أطلقت الدالة استثناءً. */ using Loki :: CheckFor ;namespace wikipedia :: examples {export class GeoPoint { private : /// تتحقق هذه الدالة من جميع ثوابت الكائن. bool isValid () const { assert ( this ); assert ( latitude >= -90.0 ); assert ( latitude <= 90.0 ); assert ( longitude >= -180.0 ); assert ( longitude <= 180.0 ); return true ; }درجات خط العرض ؛ ///< الدرجات من خط الاستواء. الموجب شمالاً، والسالب جنوباً. درجات خط الطول ؛ ///< الدرجات من خط غرينتش. الموجب شرقاً، والسالب غرباً. عام : نقطة جغرافية ( درجات خط العرض ، درجات خط الطول )؛/// تقوم دالة Move بنقل موقع GeoPoint. void move ( Degrees latChange , Degrees lonChange ) { // يستدعي كائن التحقق IsValid عند دخول الدالة وخروجها للتحقق من صحة كائن GeoPoint هذا. يضمن المدقق أيضًا أن دالة GeoPoint::move لن تُطلق أي استثناء. CheckFor < const GeoPoint >:: CheckForNoThrow checker ( this , & isValid );latitude += latChange ; if ( latitude >= 90.0f ) { latitude = 90.0f ; } if ( latitude <= -90.0f ) { latitude = -90.0f ; }longitude += lonChange ; while ( longitude >= 180.0f ) { longitude -= 360.0f ; } while ( longitude <= -180.0f ) { longitude += 360.0f ; } } };}جافا
هذا مثال على ثابت فئة في لغة برمجة جافا باستخدام لغة نمذجة جافا . يجب أن يظل الثابت صحيحًا بعد انتهاء المُنشئ، وعند دخول وخروج جميع الدوال الأعضاء العامة. ينبغي للدوال الأعضاء العامة تحديد الشروط المسبقة واللاحقة لضمان ثبات الفئة.
public class Date { int /*@spec_public@*/ day ; int /*@spec_public@*/ hour ;/*@invariant day >= 1 && day <= 31; @*/ //class invariant /*@invariant hour >= 0 && hour <= 23; @*/ //class invariant/*@ @requires d >= 1 && d <= 31; @requires h >= 0 && h <= 23; @*/ public Date ( int d , int h ) { // constructor day = d ; hour = h ; }/*@ @requires d >= 1 && d <= 31; @ensures day == d; @*/ public void setDay ( int d ) { day = d ; }/*@ @requires h >= 0 && h <= 23; @ensures hour == h; @*/ public void setHour ( int h ) { hour = h ; } }انظر أيضاً
- البرمجة القائمة على الثوابت - منهجية البرمجة
مراجع
- ↑ ماير، برتراند. بناء البرمجيات الموجهة للكائنات ، الطبعة الثانية، برنتيس هول، 1997، ص 570.
- ↑ إي. غاما، آر. هيلم، آر. جونسون، وجيه. فليسيدس. أنماط التصميم: عناصر البرمجيات القابلة لإعادة الاستخدام والموجهة للكائنات . أديسون-ويسلي، ريدينغ، ماساتشوستس، 1995، ص 20.
- ↑ وثائق بايثون الرسمية، عبارة التأكيد
- ↑ "دالة التأكيد في PHP" . مؤرشفة من الأصل بتاريخ 21-03-2001.
- ↑ "console: assert() static method - Web APIs | MDN" . MDN Web Docs . 2025-07-04 . تم الاطلاع عليه بتاريخ 2025-08-24 .
- ↑ "دليل مرجع Ada 7.3.2 ثوابت النوع" . ada-auth.org . تم الاطلاع عليه بتاريخ 27-11-2022 .
- ↑ "البرمجة التعاقدية - لغة البرمجة D" . dlang.org . تم الاطلاع عليه بتاريخ 29-10-2020 .
- الفصل الدراسي (برمجة الحاسوب)
