Javaالكلاس و الكائن في جافا
- مفهوم الكلاس في جافا
- مفهوم الكائن في جافا
- علاقة الكائن بالكلاس في جافا
- مفهوم الكونستركتور في جافا
- الكلمة
this
في جافا
مفهوم الكلاس في جافا
Class: نكتبها كلاس في العربية. و الكلاس عبارة عن حاوية كبيرة تستطيع أن تحتوي على كل الكود من متغيرات و دوال و كائنات إلخ..
لتعريف كلاس جديد يكفي فقط كتابة الكلمة class
, ثم وضع إسم له, ثم فتح أقواس تحدد بدايته و نهايته. مثال:
مثال
class ClassName { }
الآن سنقوم بتعريف كلاس جديد يحتوي على 4 متغيرات, بالإضافة إلى دالة تعرض قيم هذه المتغيرات عندما يتم إستدعاءها.
مثال
class Person { String name; String gender; String job; int age; void printInfo() { System.out.println("Name: " +name); System.out.println("Gender: " +gender); System.out.println("Job: " +job); System.out.println("Age: " +age); } }
هنا قمنا بتعريف كلاس إسمه Person
يحتوي على 4 متغيرات بالإضافة إلى دالة تعرض قيم هذه المتغيرات عندما يتم إستدعاءها.
مفهوم الخصائص
أي متغيرات يتم تعريفها بداخل كلاس و خارج أي دالة تسمى خصائص (Attributes), و هذا يعني أن أي كائن من هذا الكلاس سيكون عنده هذه الخصائص.
تستطيع التعامل مع هذه الخصائص من الكائن مباشرةً, بينما المتغيرات العادية لا يمكنك التعامل معها من الكائن.
المتغيرات التي يتم وضعها كباراميترات أو التي يتم تعريفها بداخل الدوال تسمى متغيرات عادية.
برنامج Netbeans يلون أسماء الخصائص باللون الأخضر, لكي يساعدك في التفريق بين المتغيرات العادية و المتغيرات التي يتم إعتبارها خصائص.
و تذكر أن المتغيرات تسمى خصائص, لأن أي كائن من هذا الكلاس سيملك نسخته الخاصة منها.
مفهوم الكائن في جافا
object: تعني كائن في اللغة العربية. و الكائن عبارة عن نسخة مطابقة لكلاس معين.
بما أن الكائن عبارة عن نسخة من الكلاس, يمكننا القول أنه لا يمكن إنشاء كائن إذا لم يكن هناك كلاس.
إذاً في مفهوم برمجة الكائنات نقوم بإنشاء كلاس معين يسمونه blue print أي (النسخة الخام أو النسخة الأصلية) , و بعدها ننشئ نسخة أو أكثر من هذا الكلاس و نفعل بها ما نريد بدون أن نغير محتويات الكلاس الأساسي و هكذا نكون حافظنا على كودات الكلاس الأساسي لأننا نعدل على النسخ و ليس عليه مباشرةً.
بما أن الكائن عبارة عن نسخة من الكلاس. لتعريف كائن من كلاس معين يجب وضع إسم الكلاس ثم وضع إسم للكائن.
مثال
Person ahmad = new Person();
هنا قمنا بتعريف كائن من الكلاس Person
إسمه ahmad
.
إذاً الكائن ahmad
سيكون عنده نسخة خاصة فيه من خصائص الكلاس Person
.
ملاحظة: الكود new Person()
هو الذي يقوم فعلياً بتوليد كائن من الكلاس. و هو يعطي قيم أولية للخصائص الموجودة فيه و ستفهم ذلك لاحقاً.
سنقوم الآن بكتابة نفس الكود السابق على مرحلتين لتحصل على كائن من الكلاس Person
.
مثال
Person ahmad; // Person سيمثل كائن من الكلاس ahmad هنا قلنا أن ahmad = new Person(); // Person يمثل كائن من الكلاس ahmad هنا أصبح ,ahmad و بعدها قمنا بتخزينه في Person هنا قمنا بتوليد كائن من الكلاس
طريقة التعامل مع الكائنات
- نقوم بإنشاء كائن من الكلاس.
- بعدها نقوم بإدخال قيم لخصائصه, إستدعاء دواله إلخ..
لاستدعاء أي شيء موجود في الكائن الذي أنشأناه
- نضع إسم الكائن.
- ثم نقطة.
- ثم الشيء الذي نريد الوصول إليه ( سواء إسم متغير أو دالة ).
نصائح عليك إتباعها
- يفضل إنشاء كل كلاس في ملف جافا خاص.
- إبدأ إسم الكلاس دائماً بحرف كبير.
- إبدأ إسم الكائن دائماً بحرف صغير.
علاقة الكائن بالكلاس في جافا
الكائنات تساعد المبرمج كثيراً, فمثلاً إذا كنت تنوي إنشاء برنامج بسيط لحفظ معلومات أشخاص, هل ستنشئ كلاس لكل شخص ؟!
طبعاً لا, بل تنشئ كلاس واحد فقط يمثل شخص, و تضع فيه الأشياء الأساسية التي تريدها أن تكون موجودة عند كل شخص. ثم تنشئ منه كائنات قدر ما شئت, و عندها يصبح كل كائن من هذا الكلاس عبارة عن شخص له معلوماته الخاصة.
كما تلاحظ قمنا بإنشاء كلاس يحتوي على المعلومات الأساسية التي نريد تعبئتها لكل شخص.
بعدها قمنا بإنشاء 4 كائنات ( أي 4 أشخاص ), ثم قمنا بإدخال معلومات خاصة لكل كائن فيهم.
الآن في حال قمت بإضافة أي متغير أو دالة جديدة في الكلاس Person
, فإن أي كائن من هذا الكلاس سيملك نسخة من الشيء الجديد الذي أضفته.
و في حال قمت بتعديل كود معين في الكلاس Person
, فأيضاً سيتم تعديل هذا الكود عند جميع الكائنات من هذا الكلاس.
مثال
الآن سنقوم بإنشاء الكلاس Person
و إنشاء كائنات منه في الكلاس الذي يحتوي على الدالة main()
.
إنتبه: يجب إنشاء الكلاس Person
و الكلاس Main
في نفس المجلد ( أي نفس الـ package ) حتى يعمل الكود بشكل صحيح. ستفهم السبب في الدرس التالي.
مثال
public class Person { // هنا قمنا بتعريف 4 خصائص String name; String gender; String job; int age; // هنا قمنا بتعريف دالة تطبع محتوى كل خاصية عندما يتم استدعاءها void printInfo() { System.out.println("Name: " +name); System.out.println("Gender: " +gender); System.out.println("Job: " +job); System.out.println("Age: " +age); System.out.println(); } }
public class Main { public static void main(String[] args) { // Person هنا قمنا بإنشاء كائنات من الكلاس Person p1 = new Person(); // سيمثل محمد p1 الكائن Person p2 = new Person(); // سيمثل روز p2 الكائن Person p3 = new Person(); // سيمثل أحمد p3 الكائن Person p4 = new Person(); // سيمثل ربيع p4 الكائن // p1 هنا قمنا بتحديد خصائص الكائن p1.name = "Mhamad"; p1.gender = "Male"; p1.job = "Programmer"; p1.age = 21; // p2 هنا قمنا بتحديد خصائص الكائن p2.name = "Rose"; p2.gender = "Female"; p2.job = "Secretary"; p2.age = 22; // p3 هنا قمنا بتحديد خصائص الكائن p3.name = "Ahmad"; p3.gender = "Male"; p3.job = "Doctor"; p3.age = 34; // p4 هنا قمنا بتحديد خصائص الكائن p4.name = "Rabih"; p4.gender = "Male"; p4.job = "Engineer"; p4.age = 27; // هنا قمنا بعرض خصائص كل كائن p1.printInfo(); p2.printInfo(); p3.printInfo(); p4.printInfo(); } }
سنحصل على النتيجة التالية عند التشغيل.
Name: Mhamad Gender: Male Job: Programmer Age: 21 Name: Rose Gender: Female Job: Secretary Age: 22 Name: Ahmad Gender: Male Job: Doctor Age: 34 Name: Rabih Gender: Male Job: Engineer Age: 27
مفهوم الكونستركتور في جافا
Constructor: تكتب كونستركتور بالعربية.
من أهم الأشياء التي عليك التفكير بها بعد إنشاء كلاس جديد, هي تسهيل طريقة خلق كائنات من هذا الكلاس.
من هنا جائت فكرة الكونستركتور و الذي هو عبارة عن دالة لها نوع خاص, يتم إستدعائها أثناء إنشاء كائن لتوليد قيم أولية للخصائص الموجودة فيه.
بما أنه لا يمكن إنشاء كائن من كلاس إلا من خلال كونستركتور, سيقوم مترجم جافا بتوليد كونستركتور إفتراضي فارغ عنك إذا وجد أن الكلاس الذي قمت بتعريفه لا يحتوي على أي كونستركتور.
مثال
إذا قمنا بتعريف كلاس إسمه Person
و لم نقم بتعريف كونستركتور له كما في الكلاس التالي.
class Person { }
سيقوم المترجم بإنشاء كونستركتور فارغ بشكل تلقائي عنا كالتالي.
class Person { public Person() { } }
نقاط مهمة حول الكونستركتور
- كل كلاس يتم إنشاؤه يحتوي على كونستركتور واحد على الأقل. حتى إن لم تقم بتعريف أي كونستركتور في الكلاس فإن مترجم جافا سيقوم بإنشاء واحد إفتراضي عنك.
- في كل مرة يتم فيها إنشاء كائن جديد من الكلاس، معنى ذلك أنه تم استدعاء أحد الكونستركتورات الخاصة به.
- الكونستركتور يجب أن يحمل نفس إسم الكلاس.
- نوع الكونستركتور في الغالب يكون
public
ليكون بالإمكان الوصول إليه من أي مكان. - في حال قمت بتعريف كونستركتور، لن يقوم المترجم بإنشاء واحد إفتراضي، أي لن يعود هناك كونستركتور إفتراضي.
- في حال قمت بإنشاء كونستركتور أو أكثر، يمكنك دائماً إنشاء كونستركتور فارغ حتى تستخدمه إن كنت لا تريد إعطاء قيم أولية محددة للخصائص عند إنشاء الكائن.
الآن سنرجع إلى الكلاس Person
, و سنضيف فيه 2 كونستركتور, واحد فارغ ( أي مثل الإفتراضي ), و آخر يمكننا من خلاله إدخال قيم مباشرةً في الخصائص الموجودة في الكائن بدل إستدعاء كل خاصية موجودة فيه.
مثال
public class Person { // هنا قمنا بتعريف 4 خصائص String name; String gender; String job; int age; // إفتراضي constructor فارغ, أي كأننا قمنا بتعريف constructor هنا قمنا بتعريف public Person() { } // ثاني, الهدف منه إعطاء قيم لجميع الخصائص الموجودة في الكائن عند إنشاءه مباشرةً constructor هنا قمنا بتعريف // عليك إدخال 4 قيم من نفس النوع و بالترتيب الموضوع constructor عند استدعاء هذا الـ public Person(String n, String s, String j, int a) { name = n; // name سيتم وضعه كقيمة للخاصية n الذي سيتم تخزينه في String الـ gender = s; // gender سيتم وضعه كقيمة للخاصية s الذي سيتم تخزينه في String الـ job = j; // job سيتم وضعه كقيمة للخاصية j الذي سيتم تخزينه في String الـ age = a; // age سيتم وضعه كقيمة للخاصية a الذي سيتم تخزينه في int الـ } // هنا قمنا بتعريف دالة تطبع محتوى كل خاصية عندما يتم استدعاءها void printInfo() { System.out.println("Name: " +name); System.out.println("Gender: " +gender); System.out.println("Job: " +job); System.out.println("Age: " +age); System.out.println(); } }
public class Main { public static void main(String[] args) { // Person هنا قمنا بإنشاء كائنات من الكلاس Person p1 = new Person("Mhamad", "Male", "Programmer", 21); // يمثل الشخص محمد مع تحديد كامل خصائصه p1 الكائن Person p2 = new Person("Rose", "Female", "Secretary", 22); // يمثل الشخص روز مع تحديد كامل خصائصه p2 الكائن Person p3 = new Person("Ahmad", "Male", "Doctor", 34); // يمثل الشخص أحمد مع تحديد كامل خصائصه p3 الكائن Person p4 = new Person("Rabih", "Male", "Engineer", 27); // يمثل الشخص ربيع مع تحديد كامل خصائصه p4 الكائن // الفارغ, فإضطررنا إلى إدخال قيمة لكل خاصية موجودة فيه constructor هنا قمنا بإنشاء كائن جديد باستخدام الـ Person p5 = new Person(); // p5 هنا قمنا بتحديد خصائص الكائن p5.name = "Lina"; p5.gender = "Female"; p5.job = "Graphic Designer"; p5.age = 24; // هنا قمنا بعرض خصائص كل كائن p1.printInfo(); p2.printInfo(); p3.printInfo(); p4.printInfo(); p5.printInfo(); } }
سنحصل على النتيجة التالية عند التشغيل.
Name: Mhamad Gender: Male Job: Programmer Age: 21 Name: Rose Gender: Female Job: Secretary Age: 22 Name: Ahmad Gender: Male Job: Doctor Age: 34 Name: Rabih Gender: Male Job: Engineer Age: 27 Name: Lina Gender: Female Job: Graphic Designer Age: 24
المتغيرات التي يتم وضعها في الكلاس تقسم إلى ثلاث فئات أساسية ذكرناها في الجدول التالي.
بالإنجليزية | معناها |
---|---|
Local Variables | هي المتغيرات التي يتم تعريفها بداخل أي دالة, كونستركتور, أو بداخل block ( مثل الحلقات, الجملة switch إلخ.. ). |
Instance Variables | هي المتغيرات التي يتم تعريفها بداخل الكلاس و خارج حدود أي دالة, كونستركتور, أو block. تسمى أيضاً Global Variables. |
Class Variables | هي المتغيرات التي يتم تعريفها كـ static بداخل الكلاس و خارج حدود أي دالة, كونستركتور, أو block. |
مثال
class VariablesTypes { // block لأنه تم تعريفهم بداخل الكلاس و خارج أي دالة أو Instance Variables تعتبر ( a, b, c, d ) المتغيرات // ستفهم معناها في الدرس التالي, لكننا وضعناها فقط لتفهم الأسماء المستخدمة ( public, protected, private ) الكلمات int a; public int b; protected int c; private int d; // static لأن نوعه Class Variable يعتبر e المتغير static int e; // لأنه تم تعريفها بداخل الدالة Local Variables تعتبر ( x, y, z ) المتغيرات public int sum(int x, int y) { int z = x + y; return z; } }
الكلمة this
في جافا
الكلمة this
هي كلمة محجوزة في لغة جافا, و هي تستخدم للإشارة إلى الـ Global Variables, و تستخدم أيضاً للإشارة إلى الكائن الحالي. و يمكن استخدامها في أماكن عديدة ستتعرف عليها في دروس مقبلة.
في هذا الدرس سنستخدمها للتفرقة بين المتغيرات التي تم تعريفها بداخل الدوال Local Variables و بين المتغيرات التي تم تعريفها بداخل الكلاس و خارج الدوال Global Variables.
سنرجع إلى الكلاس Person
و سنقوم باستخدام الكلمة this
عدة مرات لمعرفة تأثيرها على الكود.
في هذا المثال لم نغير أي كود كان موجود, لكننا أضفنا كلمة this
في كل مكان كنا نقصد فيه أننا نريد الوصول للخصائص.
المثال الأول
public class Person { String name; String gender; String job; int age; public Person() { } // لأن أسماء الباراميترات الموضوعة ليست نفسها أسماء الخصائص this هنا لا يوجد داعي لاستخدام الكلمة public Person(String n, String s, String j, int a) { this.name = n; // الموجودة في الكلاس name الموجود في الدالة, سيتم وضعها في الخاصية n القيمة التي سيتم إدخالها في المتغير this.gender = s; // الموجودة في الكلاس gender الموجود في الدالة, سيتم وضعها في الخاصية s القيمة التي سيتم إدخالها في المتغير this.job = j; // الموجودة في الكلاس job الموجود في الدالة, سيتم وضعها في الخاصية j القيمة التي سيتم إدخالها في المتغير this.age = a; // الموجودة في الكلاس age الموجود في الدالة, سيتم وضعها في الخاصية a القيمة التي سيتم إدخالها في المتغير } // لأن الدالة لا تحتوي على باراميترات و بالتالي سيفهم المترجم أنك تقصد عرض قيم الخصائص الموجودة في الكائن حتى لو لم تستخدمها this هنا لا يوجد داعي لاستخدام الكلمة void printInfo() { System.out.println("Name: " +this.name); System.out.println("Gender: " +this.gender); System.out.println("Job: " +this.job); System.out.println("Age: " +this.age); System.out.println(); } }
سنحصل على نفس النتيجة السابقة عند التشغيل.
Name: Mhamad Gender: Male Job: Programmer Age: 21 Name: Rose Gender: Female Job: Secretary Age: 22 Name: Ahmad Gender: Male Job: Doctor Age: 34 Name: Rabih Gender: Male Job: Engineer Age: 27 Name: Lina Gender: Female Job: Graphic Designer Age: 24
في هذا المثال استخدمنا الكلمة this
عند الحاجة لها فقط.
فعلياً، قمنا بوضع أسماء للباراميترات كأسماء الخصائص في الكونستركتور فكان يجب وضع الكلمة this
عند الحاجة للتفرقة بين الباراميترات و الخصائص حتى لا تحدث أخطاء منطقية عند تشغيل البرنامج.
المثال الثاني
public class Person { String name; String gender; String job; int age; public Person() { } // للتفرقة بين الباراميترات و الخصائص الموجودة في الكائن this هنا يجب إستخدام الكلمة public Person(String name, String gender, String job, int age) { this.name = name; // الموجودة في الكلاس name الموجود في الدالة, سيتم وضعها في الخاصية name القيمة التي سيتم إدخالها في المتغير this.gender = gender; // الموجودة في الكلاس gender الموجود في الدالة, سيتم وضعها في الخاصية gender القيمة التي سيتم إدخالها في المتغير this.job = job; // الموجودة في الكلاس job الموجود في الدالة, سيتم وضعها في الخاصية job القيمة التي سيتم إدخالها في المتغير this.age = age; // الموجودة في الكلاس age الموجود في الدالة, سيتم وضعها في الخاصية age القيمة التي سيتم إدخالها في المتغير } // لأن الدالة لا تحتوي على باراميترات و بالتالي سيفهم المترجم أنك تقصد عرض قيم الخصائص الموجودة في الكائن حتى لو لم تستخدمها this هنا لا يوجد داعي لاستخدام الكلمة void printInfo() { System.out.println("Name: " +name); System.out.println("Gender: " +gender); System.out.println("Job: " +job); System.out.println("Age: " +age); System.out.println(); } }
سنحصل على نفس النتيجة السابقة عند التشغيل.
Name: Mhamad Gender: Male Job: Programmer Age: 21 Name: Rose Gender: Female Job: Secretary Age: 22 Name: Ahmad Gender: Male Job: Doctor Age: 34 Name: Rabih Gender: Male Job: Engineer Age: 27 Name: Lina Gender: Female Job: Graphic Designer Age: 24
في هذا المثال وضعنا أسماء الباراميترات في الكونستركتور نفس أسماء الخصائص و لم نستخدم الكلمة this
للتفريق بينهم.
إذاً هنا لن تحدث أخطاء تؤدي إلى إيقاف البرنامج بل ستحدث أخطاء منطقية نلاحظها عند تشغيل البرنامج.
المثال الثالث
public class Person { String name; String gender; String job; int age; public Person() { } // سيسبب مشكلة لأن المترجم لن يستطيع التفرقة بين الباراميترات و الخصائص الموجودة في الكائن this هنا عدم إستخدام الكلمة // غير مفيد و يحتوي على أخطاء منطقية constructor إذاً هذا الـ public Person(String name, String gender, String job, int age) { name = name; // من جديد name سيتم وضعها في الباراميتر name القيمة التي سيتم إدخالها في المتغير gender = gender; // من جديد gender سيتم وضعها في الباراميتر gender القيمة التي سيتم إدخالها في المتغير job = job; // من جديد job سيتم وضعها في الباراميتر job القيمة التي سيتم إدخالها في المتغير age = age; // من جديد age سيتم وضعها في الباراميتر age القيمة التي سيتم إدخالها في المتغير } // لأن الدالة لا تحتوي على باراميترات و بالتالي سيفهم المترجم أنك تقصد عرض قيم الخصائص الموجودة في الكائن حتى لو لم تستخدمها this هنا لا يوجد داعي لاستخدام الكلمة void printInfo() { System.out.println("Name: " +name); System.out.println("Gender: " +gender); System.out.println("Job: " +job); System.out.println("Age: " +age); System.out.println(); } }
سنحصل على النتيجة التالية عند التشغيل، لاحظ أن الكائنات التي استخدمت الكونستركتور الأول فقط هي التي حدث فيها أخطاء منطقية.
Name: null Gender: null Job: null Age: 0 Name: null Gender: null Job: null Age: 0 Name: null Gender: null Job: null Age: 0 Name: null Gender: null Job: null Age: 0 Name: Lina Gender: Female Job: Graphic Designer Age: 24