الـ enum في جافا


(عمار الخوالدة) #1

بسم الله الرحمن الرحيم …

أهلا باعضاء وزوار مجتمع اسس الكرام ، أقدم لكم اليوم شرحا للـ enum في لغة جافا .


فهرس الموضوع :

  • أولا: ما هو الـ enum.
  • ثانيا : طريقة كتابة الـ enum.
  • ثالثا : تحديد قيمة للـ enum.
  • رابعا : استدعاء القيم من الـ enum.
  • خامسا : المراجع التي تم استخدامها .

أولا : ما هو الـ enum .

تستطيع القول ان الـ enum هي طريقة تنظيمية للثوابت (Constants) في الكود بحيث تجمع الثوابت اللتي لها علاقة ببعضها تحت فئة واحدة بطريقة تنظم الوصول اليها .

مثلا بإمكانك عمل enum يحتوي ثوابت تتعلق بايام الاسبوع فهذه الاشياء ثابتة ومرتبطة دائما مع بعضها ، أو اتجاهات البوصلة (شمال،جنوب،شرق،غرب) وغيرها من الأمور المتعلقة ببعضها .

ملاحظة مهمة : يفضل عند كتابة أسماء الثوابت كتابتها بالكامل بحروف كبيرة .
مثال : NORTH,SOUTH .


ثانيا : طريقة كتابة الـ enum .

أولا عليك أن تنشئ كلاس عادي وتستبدل كلمة class بكلمة enum فقط ، وبامكانك أيضا إنشاء ملف جديد من نوع enum ، وهذه طريقة انشائه في الـ NetBeans :

بعد انشاء ملف ال enum ستكتب فيه الثوابت بدون تحديد نوعها ولا كتابة كلمة final
وستكتب كالتالي :

CONSA,CONSC,CONSB;

تكتب الثوابت بفاصلة بين كل ثابت مع وضع الفاصلة المنقوطة في النهاية ، لاستدعاء المتغير ما عليك الا كتابة اسم الـ enum وتحديد اسم الثابت ، افترض ان لدينا enum بالشكل الآتي :

    public enum accEnum {
        A,B,C;
        
    }

لاحظ أننا لم نحدد قيم الثوابت بعد ، إذهب الآن إلى الكلاس الرئيسي واستدعي الثابت A مثلا بهذه الطريقة:

    System.out.println(accEnum.A);

الآن نفذ البرنامج ولاحظ نتيجة الطباعة :

لاحظ أن نتيجة التنفيذ قد أعطت اسم الثابت نفسه ، بشكل افتراضي عند عدم تحديد قيمة للثابت يتم طباعة إسم الثابت .
ملاحظة اخرى ربما انتبهت لها ، لا بد انك تعرف ان الثوابت يوضع قبل اسمها كلمة final لكن ربما لاحظت ان ثوابت الـ enum لا تعد final فقط بل تعد static أيضا بدليل أنك تستدعي الثابت دون الحاجة لتعريف كائن من الـ enum .


ثالثا : تحديد قيمة للـ enum

عليك أن تعرف بأن بإمكانك تحديد أكثر من قيمة للثابت الواحد ويوجد قواعد معينة لكتابة الثوابت بداخل ملف الـ enum يجب أن تلتزم بها :

  • يجب أن تكون كل القيم بنفس النوع وعلى نفس الثوابت وبنفس الترتيب ، مثلا لو كان نوع القيمة الأولى من الثابت A هو String والثاني int يجب أن يكون النوع الأول String والثاني int في جميع الثوابت .

  • يجب إضافة متغير عن كل نوع ، بحسب المثال في النقطة السابقة يجب اضافة متغيرين الأول String والثاني int

  • يجب إضافة Constructor بالإضافة إلى وجوب وجود بارمترات من نفس نوع قيم الثوابت ونفس الترتيب ، بحسب المثال السابق يجب وجود بارمترين الأول String والثاني int

الآن لننتقل إلى المثال (شرح الأكواد بالتفصيل بداخل Comments في الكود ) :

    public enum accEnum {
        /*
        لاحظ وجود قيمتين من كل ثابت الأولى نصية والثانية عددية
        لاحظ أيضا أننا لم نحدد نوعها وستعرف كيف تم تحديد النوع فيما بعد
        */
        A("Acc", 2015) , B("Best" , 2009) ;
        
        /*
        انظر إلى المتغيرا ت ولاحظ أننا عرفنا اثنين فقط واحد عن كل نوع
        إياك أن تخطئ وتعرف  أربعة وسنشرح فائدة هذه المتغيرات وسبب تعريفها
        فيما بعد الآن عليك فقط أن تعرف أننا سنعرف متغيرات بنفس أنواع قيم الثوابت
        لا تستعجل سنشرح كل شيء وستفهمه جيدا بإذن الله
        */
        public String name ;
        public int date ;
        
        
        /*
        ننتقل إلى الكلام الدسم
       هنا يتم تحديد أنواع قيم الثوابت
        لاحظ أن بارميترات الدالة هي من تحدد النوع
        لكن كيف يمكن لهذه الدالة ان تحدد النوع ؟
        هذا ما سأوضحه عند شرح استدعاء قيم الثوابت
        */
        private accEnum(String siteName , int createDate){
            
            /*
            هنا يتم مساواة البارمترات بالمتغيرات في الاعلى
            
          ستتضح فائدة ذلك عندما نشرح استدعاء القيم
            */
            this.name = siteName;
            this.date = createDate;
        }    
        
    }

الآن بعد أن تم توضيح هذه الأمور اللتي لم تفهمها غالبا سنشرح طريقة الاستدعاء اللتي ستوضح الأمور اللتي بقيت عالقة في الكود السابق .


رابعا : إستدعاء القيم من الـ enum .

انتقل إلى الكلاس الرئيسي لنتعلم طريقة الاستدعاء :

لو وضعت الكود الآتي :


           System.out.println(accEnum.B);

سيقوم بطباعة إسم الثابت وهو B ولن يطبع أيا من القيم .
هل تذكر المتغيران اللذان وضعناهما ؟

شاهد الكود الآتي اللذي سيجعلك تعرف سبب وجودهما :


            System.out.println(accEnum.A.name);
            System.out.println(accEnum.A.date);
            System.out.println(accEnum.B.name);
            System.out.println(accEnum.B.date);

لاحظ أننا نستدعي المتغير من خلال الثابت ومنه تستدعى القيم وهذه صورة المخرجات :

لكن كيف يحصل كل هذا ؟ كيف يستدعى المتغير من خلال الثابت ! :astonished:

تفسير الأمر ببساطة كالآتي :

عندما تستخدم ثابتا بداخل Enum فهو يعامل معاملة الكائن (Object)
بالتالي فعندما كتبنا قيم الثابت بهذه الطريقة

        A("Acc", 2015) ;

فأنت فعليا تقوم باستدعاء الـ Constructor بين الأقواس ، ولا تنسى أن الـ Constructor في مثالنا يحوي بارمترين الأول String والثاني int ، بدأت تتوضح الأمور أليس كذلك ؟

هكذا فهمنا كيف تم تحديد نوع البيانات و لم يجب وضع دالة Constructor بشكل الزامي ، الآن يبقى أن نعرف ما فائدة المتغيرات التي أضفناها .

لاحظ الأكواد بداخل الـConstructor :

      public String name ;
        public int date ;

        private accEnum(String siteName , int createDate){
            this.name = siteName;
            this.date = createDate;
        }    

لاحظ أننا جعلنا قيمة المتغير تساوي قيمة البارميتر وبالتالي تساوي قيمة البيانات اللتي مررها الكائن أو الثابت إلى البارميتر، وبما أن الثوابت تعتبر كائنات بالنسبة للـ enum لذلك لم نعرف 4 متغيرات مثلا فلا حاجة لذلك فكل كائن لديه نسخته الخاصة من المتغير .


خامسا : المراجع اللتي تم استخدامها .



(أحمد كريز) #2

##كيف قمت بالتلوين :grin:


(عمار الخوالدة) #3

هذي صالح الله يعطيه العافية علمني اياها

شوف الموضوع

http://aosus.org/t/markdown/122

(الألوان ما تلونها يدوي فقط للأكواد على الاغلب)