الكلاس و الكائن في جافا | java the class and the object

 الكلاس في جافا

Class: نكتبها كلاس في العربية. و الكلاس عبارة عن حاوية كبيرة تستطيع أن تحتوي على كل الكود من متغيرات و دوال و كائنات إلخ..

Category: we write it class in Arabic. Contains objects containing high organisms. To define a new class, it is sufficient to just write the word class, put a name for it, then open parentheses specifying its beginning and end. Example:

لتعريف كلاس جديد يكفي فقط كتابة الكلمة class, ثم وضع إسم له, ثم فتح أقواس تحدد بدايته و نهايته. مثال:

مثال

class ClassName {

} 
		

الآن سنقوم بتعريف كلاس جديد يحتوي على 4 متغيرات, بالإضافة إلى دالة تعرض قيم هذه المتغيرات عندما يتم إستدعاءها.

مثال

Person.java
class Person {

    String name;
    String sex;
    String job;
    int age;

    void printInfo() {
        System.out.println("Name: " +name);
        System.out.println("Sex: " +sex);
        System.out.println("Job: " +job);
        System.out.println("Age: " +age);
    }

} 
		

هنا قمنا بتعريف كلاس إسمه Person يحتوي على 4 متغيرات بالإضافة إلى دالة تعرض قيم هذه المتغيرات عندما يتم إستدعاءها.


مفهوم الخصائص في جافا

أي متغيرات يتم تعريفها بداخل كلاس و خارج أي دالة تسمى خصائص (Attributes), و هذا يعني أن أي كائن من هذا الكلاس سيكون عنده هذه الخصائص.
تستطيع التعامل مع هذه الخصائص من الكائن مباشرةً, بينما المتغيرات العادية لا يمكنك التعامل معها من الكائن.
المتغيرات التي يتم وضعها كباراميترات أو التي يتم تعريفها بداخل الدوال تسمى متغيرات عادية.

The concept of properties in Java Any variables that are defined inside a class and outside any function called Attributes, and this means that any object from this class will have these properties. You can manipulate these properties directly from the object, while normal variables cannot be manipulated from the object. Variables that are placed parameters or that are defined within functions are called regular variables.

ملاحظة

برنامج 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 هنا قمنا بتوليد كائن من الكلاس
		


طريقة التعامل مع الكائنات

  • نقوم بإنشاء كائن من الكلاس.

  • بعدها نقوم بإدخال قيم لخصائصه, إستدعاء دواله إلخ..



لاستدعاء أي شيء موجود في الكائن الذي أنشأناه

  1. نضع إسم الكائن.

  2. ثم نقطة.

  3. ثم الشيء الذي نريد الوصول إليه ( سواء إسم متغير أو دالة ).



نصائح عليك إتباعها

  • يفضل إنشاء كل كلاس في ملف جافا خاص.

  • إبدأ إسم الكلاس دائماً بحرف كبير.

  • إبدأ إسم الكائن دائماً بحرف صغير.

علاقة الكائن بالكلاس في جافا

الكائنات تساعد المبرمج كثيراً, فمثلاً إذا كنت تنوي إنشاء برنامج بسيط لحفظ معلومات أشخاص, هل ستنشئ كلاس لكل شخص ؟!
طبعاً لا, بل تنشئ كلاس واحد فقط يمثل شخص, و تضع فيه الأشياء الأساسية التي تريدها أن تكون موجودة عند كل شخص. ثم تنشئ منه كائنات قدر ما شئت, و عندها يصبح كل كائن من هذا الكلاس عبارة عن شخص له معلوماته الخاصة.



كما تلاحظ قمنا بإنشاء كلاس يحتوي على المعلومات الأساسية التي نريد تعبئتها لكل شخص.
بعدها قمنا بإنشاء 4 كائنات ( أي 4 أشخاص ), ثم قمنا بإدخال معلومات خاصة لكل كائن فيهم.

الآن في حال قمت بإضافة أي متغير أو دالة جديدة في الكلاس Person, فإن أي كائن من هذا الكلاس سيملك نسخة من الشيء الجديد الذي أضفته.
و في حال قمت بتعديل كود معين في الكلاس Person, فأيضاً سيتم تعديل هذا الكود عند جميع الكائنات من هذا الكلاس.



مثال

الآن سنقوم بإنشاء الكلاس Person و إنشاء كائنات منه في الكلاس الذي يحتوي على الدالة main().
إنتبه: يجب إنشاء الكلاس Person و الكلاس Main في نفس المجلد ( أي نفس الـ package ) حتى يعمل الكود بشكل صحيح. ستفهم السبب في الدرس التالي.

مثال

Person.java
public class Person {
 
    // هنا قمنا بتعريف 4 خصائص
    String name;
    String sex;
    String job;
    int age;
 
    // هنا قمنا بتعريف دالة تطبع محتوى كل خاصية عندما يتم استدعاءها
    void printInfo() {
        System.out.println("Name: " +name);
        System.out.println("Sex: " +sex);
        System.out.println("Job: " +job);
        System.out.println("Age: " +age);
        System.out.println();
    }
 
}
		

Main.java
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.sex  = "Male";
        p1.job  = "Programmer";
        p1.age  = 21;
 
        // p2 هنا قمنا بتحديد خصائص الكائن
        p2.name = "Rose";
        p2.sex  = "Female";
        p2.job  = "Secretary";
        p2.age  = 22;
 
        // p3 هنا قمنا بتحديد خصائص الكائن
        p3.name = "Ahmad";
        p3.sex  = "Male";
        p3.job  = "Doctor";
        p3.age  = 34;
 
        // p4 هنا قمنا بتحديد خصائص الكائن
        p4.name = "Rabih";
        p4.sex  = "Male";
        p4.job  = "Engineer";
        p4.age  = 27;
 
        // هنا قمنا بعرض خصائص كل كائن
        p1.printInfo();
        p2.printInfo();
        p3.printInfo();
        p4.printInfo();
 
    }
 
}
		

سنحصل على النتيجة التالية عند التشغيل.

Name: Mhamad
Sex: Male
Job: Programmer
Age: 21

Name: Rose
Sex: Female
Job: Secretary
Age: 22

Name: Ahmad
Sex: Male
Job: Doctor
Age: 34

Name: Rabih
Sex: Male
Job: Engineer
Age: 27 
		

مفهوم الكونستركتور في جافا

Constructor: تكتب كونستركتور بالعربية.
من أهم الأشياء التي عليك التفكير بها بعد إنشاء كلاس جديد, هي تسهيل طريقة خلق كائنات من هذا الكلاس.
من هنا جائت فكرة الكونستركتور و الذي هو عبارة عن دالة لها نوع خاص, يتم إستدعائها أثناء إنشاء كائن لتوليد قيم أولية للخصائص الموجودة فيه.

بما أنه لا يمكن إنشاء كائن من كلاس إلا من خلال كونستركتور, سيقوم مترجم جافا بتوليد كونستركتور إفتراضي فارغ عنك إذا وجد أن الكلاس الذي قمت بتعريفه لا يحتوي على أي كونستركتور.


مثال

إذا قمنا بتعريف كلاس إسمه Person و لم نقم بتعريف كونستركتور له كما في الكلاس التالي.

class Person {

} 
		

سيقوم المترجم بإنشاء كونستركتور فارغ بشكل تلقائي عننا كالتالي.

class Person {

    public Person() {

    }

} 
		


نقاط مهمة حول الكونستركتور

  • كل كلاس يتم إنشاءه, يحتوي على كونستركتور واحد على الأقل. و حتى إن لم تقم بتعريف أي كونستركتور, سيقوم المترجم بإنشاء واحد إفتراضي عنك.

  • في كل مرة يتم إنشاء كائن جديد, يجب استدعاء كونستركتور حتى يتم إنشاء هذا الكائن.

  • القاعدة الأساسية عند تعريف كونستركتور هي أنه يجب أن يحمل نفس إسم الكلاس و يكون نوعه public.

  • في حال قمت بتعريف كونستركتور, لن يقوم المترجم بإنشاء واحد إفتراضي, أي لن يعود هناك كونستركتور إفتراضي.

  • يمكنك تعريف أكثر من كونستركتور. و يمكنك دائماً إنشاء كونستركتور فارغ, حتى تستخدمه إن كنت لا تريد إعطاء قيم أولية محددة للخصائص عند إنشاء كائن.


الآن سنرجع إلى الكلاس Person, و سنضيف فيه 2 كونستركتور, واحد فارغ ( أي مثل الإفتراضي ), و آخر يمكننا من خلاله إدخال قيم مباشرةً في الخصائص الموجودة في الكائن بدل إستدعاء كل خاصية موجودة فيه.

مثال

ملاحظة: قمنا بتعليم الأسطر الجديدة التي قمنا بإضافتها في الكلاس باللون الأصفر.

Person.java
public class Person {
 
    // هنا قمنا بتعريف 4 خصائص
    String name;
    String sex;
    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 الـ
        sex = s;     // sex سيتم وضعه كقيمة للخاصية s الذي سيتم تخزينه في String الـ
        job = j;     // job سيتم وضعه كقيمة للخاصية j الذي سيتم تخزينه في String الـ
        age = a;     // age سيتم وضعه كقيمة للخاصية a الذي سيتم تخزينه في int الـ
    }
 
    // هنا قمنا بتعريف دالة تطبع محتوى كل خاصية عندما يتم استدعاءها
    void printInfo() {
        System.out.println("Name: " +name);
        System.out.println("Sex: " +sex);
        System.out.println("Job: " +job);
        System.out.println("Age: " +age);
        System.out.println();
    }
 
}
		

Main.java
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.sex  = "Female";
        p5.job  = "Graphic Designer";
        p5.age  = 24;
 
        // هنا قمنا بعرض خصائص كل كائن
        p1.printInfo();
        p2.printInfo();
        p3.printInfo();
        p4.printInfo();
        p5.printInfo();
 
    }
 
}
		

سنحصل على النتيجة التالية عند التشغيل.

Name: Mhamad
Sex: Male
Job: Programmer
Age: 21

Name: Rose
Sex: Female
Job: Secretary
Age: 22

Name: Ahmad
Sex: Male
Job: Doctor
Age: 34

Name: Rabih
Sex: Male
Job: Engineer
Age: 27

Name: Lina
Sex: 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 في كل مكان كنا نقصد فيه أننا نريد الوصول للخصائص.

المثال الأول

Person.java
public class Person {
 
    String name;
    String sex;
    String job;
    int age;
 
    public Person() {
 
    }
 
    // لأن أسماء الباراميترات الموضوعة ليست نفسها أسماء الخصائص this هنا لا يوجد داعي لاستخدام الكلمة
    public Person(String n, String s, String j, int a) {
        this.name = n;     // الموجودة في الكلاس name الموجود في الدالة, سيتم وضعها في الخاصية n القيمة التي سيتم إدخالها في المتغير
        this.sex  = s;     // الموجودة في الكلاس sex الموجود في الدالة,  سيتم وضعها في الخاصية s القيمة التي سيتم إدخالها في المتغير
        this.job  = j;     // الموجودة في الكلاس job الموجود في الدالة,  سيتم وضعها في الخاصية j القيمة التي سيتم إدخالها في المتغير
        this.age  = a;     // الموجودة في الكلاس age الموجود في الدالة,  سيتم وضعها في الخاصية a القيمة التي سيتم إدخالها في المتغير
    }
 
    // لأن الدالة لا تحتوي على باراميترات و بالتالي سيفهم المترجم أنك تقصد عرض قيم الخصائص الموجودة في الكائن حتى لو لم تستخدمها this هنا لا يوجد داعي لاستخدام الكلمة
    void printInfo() {
        System.out.println("Name: " +this.name);
        System.out.println("Sex: "  +this.sex);
        System.out.println("Job: "  +this.job);
        System.out.println("Age: "  +this.age);
        System.out.println();
    }
 
}
		

سنحصل على نفس النتيجة السابقة عند التشغيل.

Name: Mhamad
Sex: Male
Job: Programmer
Age: 21

Name: Rose
Sex: Female
Job: Secretary
Age: 22

Name: Ahmad
Sex: Male
Job: Doctor
Age: 34

Name: Rabih
Sex: Male
Job: Engineer
Age: 27

Name: Lina
Sex: Female
Job: Graphic Designer
Age: 24 
		


في هذا المثال سنستخدم الكلمة this عند الحاجة لها فقط.

المثال الثاني

هنا قمنا بوضع أسماء الباراميترات مثل أسماء الخصائص.
إذاً هنا يجب وضع الكلمة this إذا كنا نريد الوصول للخصائص و إلا ستحدث أخطاء منطقية في البرنامج.

Person.java
public class Person {
 
    String name;
    String sex;
    String job;
    int age;
 
    public Person() {
 
    }
 
    // للتفرقة بين الباراميترات و الخصائص الموجودة في الكائن this هنا يجب إستخدام الكلمة
    public Person(String name, String sex, String job, int age) {
        this.name = name;    // الموجودة في الكلاس name الموجود في الدالة, سيتم وضعها في الخاصية name القيمة التي سيتم إدخالها في المتغير
        this.sex  = sex;     // الموجودة في الكلاس sex الموجود في الدالة,  سيتم وضعها في الخاصية sex القيمة التي سيتم إدخالها في المتغير
        this.job  = job;     // الموجودة في الكلاس job الموجود في الدالة,  سيتم وضعها في الخاصية job القيمة التي سيتم إدخالها في المتغير
        this.age  = age;     // الموجودة في الكلاس age الموجود في الدالة,  سيتم وضعها في الخاصية age القيمة التي سيتم إدخالها في المتغير
    }
 
    // لأن الدالة لا تحتوي على باراميترات و بالتالي سيفهم المترجم أنك تقصد عرض قيم الخصائص الموجودة في الكائن حتى لو لم تستخدمها this هنا لا يوجد داعي لاستخدام الكلمة
    void printInfo() {
        System.out.println("Name: " +name);
        System.out.println("Sex: "  +sex);
        System.out.println("Job: "  +job);
        System.out.println("Age: "  +age);
        System.out.println();
    }
 
}
		

سنحصل على نفس النتيجة السابقة عند التشغيل.

Name: Mhamad
Sex: Male
Job: Programmer
Age: 21

Name: Rose
Sex: Female
Job: Secretary
Age: 22

Name: Ahmad
Sex: Male
Job: Doctor
Age: 34

Name: Rabih
Sex: Male
Job: Engineer
Age: 27

Name: Lina
Sex: Female
Job: Graphic Designer
Age: 24 
		


في هذا المثال وضعنا أسماء الباراميترات في الكونستركتور نفس أسماء الخصائص و لم نستخدم الكلمة this للتفريق بينهم.
إذاً هنا لن تحدث أخطاء تؤدي إلى إيقاف البرنامج بل ستحدث أخطاء منطقية نلاحظها عند تشغيل البرنامج.

المثال الثالث

هنا قمنا بوضع أسماء الباراميترات مثل أسماء الخصائص.
سيتسبب هذا الكود بأخطاء منطقية تظهر فقط عند تشغيل البرنامج.

Person.java
public class Person {
 
    String name;
    String sex;
    String job;
    int age;
 
    public Person() {
 
    }
 
    // سيسبب مشكلة لأن المترجم لن يستطيع التفرقة بين الباراميترات و الخصائص الموجودة في الكائن this هنا عدم إستخدام الكلمة
    // غير مفيد و يحتوي على أخطاء منطقية constructor إذاً هذا الـ
    public Person(String name, String sex, String job, int age) {
        name = name;    // من جديد name سيتم وضعها في الباراميتر name القيمة التي سيتم إدخالها في المتغير
        sex  = sex;     // من جديد sex  سيتم وضعها في الباراميتر sex  القيمة التي سيتم إدخالها في المتغير
        job  = job;     // من جديد job  سيتم وضعها في الباراميتر job  القيمة التي سيتم إدخالها في المتغير
        age  = age;     // من جديد age  سيتم وضعها في الباراميتر age  القيمة التي سيتم إدخالها في المتغير
    }
 
    // لأن الدالة لا تحتوي على باراميترات و بالتالي سيفهم المترجم أنك تقصد عرض قيم الخصائص الموجودة في الكائن حتى لو لم تستخدمها this هنا لا يوجد داعي لاستخدام الكلمة
    void printInfo() {
        System.out.println("Name: " +name);
        System.out.println("Sex: "  +sex);
        System.out.println("Job: "  +job);
        System.out.println("Age: "  +age);
        System.out.println();
    }
 
}
		

سنحصل على النتيجة التالية عند التشغيل.

لاحظ أن الكائنات التي استخدمت الكونستركتور الأول فقط هي التي حدث فيها أخطاء منطقية.

Name: null
Sex: null
Job: null
Age: 0

Name: null
Sex: null
Job: null
Age: 0

Name: null
Sex: null
Job: null
Age: 0

Name: null
Sex: null
Job: null
Age: 0

Name: Lina
Sex: Female
Job: Graphic Designer
Age: 24