تعلّم البرمجة بلغة كوتلن (37): أصناف الثوابت التعددية Enum

استمع إلى المقال
|
تحدثنا في قسم مقدمة في الكائنات، عن ما هي الكائنات Objects في البرمجة، وكيفية إنشاء أصناف Classes خاصة بنا في كوتلن. وشرحنا أيضًا، كيف يمكننا تخزين مجموعة غير محدّدة العدد من الكائنات، في تجميعة Collection، أو مصفوفة Array.
في هذا الدرس، سنستعرض صنف خاص، يسهل لنا تجميع مجموعة من الكائنات، والتي تكون ثابتة العدد والقيم بطبيعتها. وهو صنف الثوابت Constants التعددية Enum.
كلمة enum هي اختصار لكلمة enumeration والتي تعني تعداد. وهو في كوتلن، صنف خاص يمكننا من تخزين مجموعة من الثوابت في مكان واحد والتعامل معها جميعًا في نفس الوقت. وهو بالتالي، يجعل من شفرتنا أكثر وضوحًا ويزيد قابلية قراءتها.
نعلن عن الصنف enum، باستخدام الكلمتين المفتاحيتين enum class:
enum class ClassName {
// هنا نضع الثوابت التي نريد تخزينها في هذا الصنف
}
فمثلًا، إذا أردنا التعامل مع الألوان التي يتكون منها قوس قزح Rainbow، سيكون استخدام الصنف enum مثاليًا لحفظ بيانات هذه الألوان. لأنه كما نعرف، أن عددها ثابت 7، وقيمها أيضًا ثابتة: الأحمر والبرتقالي والأصفر والأخضر والأزرق والنيلي والبنفسجي:
enum class Rainbow {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}
نلاحظ أنه وضعنا أسماء الألوان بالحروف الإنجليزية الكبيرة Uppercase، وفصلنا بينها بفاصلة ( , ). هذه هي الطريقة المتّبعة لكتابة أسماء الكائنات (الثوابت) داخل صنف enum.
بالإضافة إلى ذلك، يمكننا بالطبع إنشاء صنف enum لكائنات أخرى. مثل:
أيام الإسبوع:
enum class Week {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
نوع الجنس:
enum class Gender {
MALE, FEMALE
}
مقاسات البيتزا:
enum class PizzaSize {
SMALL, MEDIUM, LARGE
}
وفقًا للطريقة المتّفق عليها في كوتلن Kotlin Coding Convention، يتم كتابة الثوابت Constants في كوتلن، باستخدام الحروف الإنجليزية الكبيرة Uppercase. أمّا إذا كان الثابت يتكون من كلمتين أو أكثر، يمكن كتابته إما بأحرف إنجليزية كبيرة مفصولة بشرطة سفلية (مثل RED_COLOR)، أو استخدام طريقة الجمل CamelCase التي تبدأ بحرف كبير (RedColor).
يمكننا طباعة قيم الثوابت في الصنف Rainbow، باستخدام اسم الصنف:
وستكون نتيجة الطباعة:
BLUE
هذه هي القيمة التي يحملها كائن الـ enum المسمى BLUE في هذه اللحظة. ولكن أليس هذا هو نفس إسم الكائن الذي وضعناه داخل الصنف Rainbow، هل هذا هو كل ما يمكن فعله مع الصنف enum؟ بالطبع لا. أصناف enum لديها الكثير من الخصائص والمزايا والتي سنمر على العديد منها بالتدريج في الفقرات أدناه.
لأن enum عبارة عن صنف، لذلك يحتوي على باني Constructor. بالتالي، يمكننا استخدام هذا الباني، لتمرير بيانات الكائنات داخل الصنف:
وضعنا خاصية أسميناها color من نوع البيانات String، داخل أقواس باني الصنف Rainbow. وفي هذه الحالة، سيكون من الإجباري تمرير قيمة هذه الخاصية في الثوابت داخل الصنف، كما يظهر في الشفرة أعلاه.
الآن عند استدعاء الكائن BLUE، يمكننا استدعاء قيمة الخاصية الخاصة به:
وستكون نتيجة الطباعة هذه المرة، هو النص الذي وضعناه بين قوسي الكائن BLUE:
Blue
يتم تمثيل الألوان في صفحات الويب، عبر استخدام الأرقام الست عشرية. فمثلَا، اللون الأحمر يتم تمثيله بهذه الطريقة:
#FF0000
حيث FF هي قيمة اللون الأحمر Red، وهي درجة التّشبّع من اللون. أمّا 00 في الوسط هي قيمة اللون الأخضر Green، وهي تعبّر عن غياب هذا اللون. والـ 00 الأخيرة هي قيمة اللون الأزرق Blue. ولغياب اللونين الأخضر والأزرق في هذا الرقم، يكون هذا الرقم الذي يمثل اللون الأحمر فقط.
بالتالي، تكون الأرقام التي تمثّل اللون الأخضر: 00FF00، واللون الأزرق: 0000FF. باستخدام هذه الطريقة، وهذه الألوان الثلاث، يتم تمثيل كل الألوان في صفحات الويب. ويعرف هذا النمط بـ RGB، كاختصار لـ Red, Green, Blue.
نحن الآن سنستفيد من هذا الأمر ونضيف خاصية rgb لصنف Rainbow:
أصبح لدينا خاصيتين لكل كائن في صنف Rainbow. يمكننا طباعة أيّاً منهما أو كليهما:
وستكون نتيجة الطباعة:
كما قلنا سابقًا، الـ enum هو عبارة عن صنف عادي. لذا يمكننا إضافة الدوال إليه أيضًا. وسنستفيد من هذه الإمكانية، في تعديل شفرتنا أعلاه لتصبح أكثر وضوحًا، بإضافة دالة تعيد معلومات كل لون عند استدعائها:
fun getColorInfo() = “The $color represented with $rgb in web colors”
هذه المرة، يمكننا استدعاء هذه الدّالة عبر استخدام صنف الـ enum، والكائن المراد الحصول على معلوماته:
وعند تنفيذ الشفرة، سيكون الناتج:
عند إضافة دالة أو أي شفرة تحت الكائنات في صنف enum، نضع فاصلة منقوطة ( ; ) بعد آخر كائن. نلاحظ أيضًا في الصورة، أنّنا استخدمنا مفهوم التغليف Encapsulation بوضعنا كلمة private قبل كل خاصية في الباني. لأنه أصبح لدينا دالة تعيد معلومات كل الكائنات في الصنف، لذلك لم يعد هناك داعي للوصول واستخدام الخاصيتين خارج الصنف.
الآن نعرف كيفية إنشاء صنف enum، وإضافة خاصيّات ودوال إليه. ولكن في حالات عملية كثيرة، لا يعد هذا كافيًا. إذ سيتوجب علينا استخدام الخاصيّات والدوال التي تأتي مع الـ enum في مكتبة كوتلن القياسية. كمثال لدينا:
لفهم عمل الخاصيّات والدوال من الفقرة السابقة، دعونا نكتبها كلها في شفرة واحدة:
لدينا في الشفرة أعلاه، الدّالة الرئيسية ()main، وصنف enum، ودالة ()isRainbowContains والتي سنستخدمها لمعرفة ما إذا كان لون معين متواجد في صنف الـ enum. سنشرح الشفرة بالتفصيل في الصورة التالية:
لن يكون هناك فرق عند طباعة المتغيرين colorName1 و colorName2، فالإثنين يطبعان اسم الكائن عند وضعهما في دالة الطباعة. ولكن، سيكون الفرق هو استخدام الخاصيّات والدوال المختلفة معهما. لأن الأول كائن من النوع String، والثاني كائن من النوع enum الخاص بنا، وهو في حالتنا هذه Rainbow.
فكما نعرف من الدروس السابقة، أنه يمكننا الدوران على التجميعات والنطاقات والمصفوفات، عبر استخدام الحلقة for. إذًا للدوران على كائنات في صنف enum، نحتاج أن تأتي في إحدى هذه الأشكال. وهذا تمامًا هو عمل دالة ()values، والتي تُجمِّع كائنات ال enum، في مصفوفة واحدة، يصبح من السهل التعامل معها عبر حلقة التكرار for.
المتغير المؤقت الذي اخترنا له اسم enum في الحلقة، سيُمثِّل كائن واحد في كل دورة للحلقة. لذا في كتلة if الشرطية، نتحقق ما إذا كان اسم الكائن الحالي، والذي نصل إليه باستخدام الخاصيّة name، يتطابق مع قيمة المعامل color.
لتجنب الأخطاء، نحتاج أيضًا إلى تحويل قيمة المعامل color إلى حروف كبيرة باستخدام دالة ()uppercase من المكتبة القياسية، لتصبح “BLACK” بدلًا عن “black” بعد التحويل. وهذا لأن أسماء الكائنات تكون بالحروف الكبيرة، فإذا لم نفعل ذلك، سيتم إعتبار أن “black” غير موجودة في صنف Rainbow.
كانت نتيجة طباعة القيمة العائدة من الدالة false، لأن “BLACK” لا يتواجد ضمن مجموعة كائنات صنف Rainbow.
هذا الدرس هو جزء من سلسلة تعليم مبادئ البرمجة بلغة كوتلن. لمُتابعة الدروس منذ البداية ومُشاهدة فهرس المحتويات يمكنك الانتقال إلى الدرس الأول من هنا.
هل أعجبك المحتوى وتريد المزيد منه يصل إلى صندوق بريدك الإلكتروني بشكلٍ دوري؟
انضم إلى قائمة من يقدّرون محتوى إكسڤار واشترك بنشرتنا البريدية.