القائمة الرئيسية

الصفحات

الكلاس والكائن والوراثه في جافا

مفهوم الكلاس في جافا

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

لتعريف كلاس جديد يكفي فقط كتابة الكلمة 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), و هذا يعني أن أي كائن من هذا الكلاس سيكون عنده هذه الخصائص.
تستطيع التعامل مع هذه الخصائص من الكائن مباشرةً, بينما المتغيرات العادية لا يمكنك التعامل معها من الكائن.
المتغيرات التي يتم وضعها كباراميترات أو التي يتم تعريفها بداخل الدوال تسمى متغيرات عادية.


ملاحظة

برنامج 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 
	

مفهوم الوراثة في جافا

وراثة: تعني Inheritance في اللغة الإنجليزية. و لقد ذكرت هذه الكلمة عدة مرات في دروس سابقة.
في جافا, الكلاس يمكنه أن يرث من كلاس آخر, و بالتالي يحصل على الدوال و المتغيرات الموجودة في هذا الكلاس.

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


مفهوم Superclass و Subclass

  • الكلاس الذي يرث من كلاس آخر يسمى Subclass و يسمى أيضاً ( derived class, extended class أو child class ).

  • الكلاس الذي يورث محتوياته لكلاس آخر يسمى Superclass و يسمى أيضاً ( base class أو parent class ).


مثال

الآن لنفترض أننا قمنا بتعريف كلاس إسمه A يحتوي على متغير إسمه x و دالة إسمها printA().
بعدها قمنا بإنشاء كلاس جديد فارغ إسمه B و قلنا أنه يرث من الكلاس A. إذاً هذا يعني أن الكلاس B أصبح يملك نسخة من جميع المتغيرات و الدوال الموجودة في الكلاس A.

إنتبه

الـ Subclass يرث كل شيء موجود في الـ Superclass بشكل تلقائي ما عدا الـكونستركتور.
مع العلم أنه يمكن استدعاء كونستركتور الـ Superclass من الـ Subclass بواسطة الكلمة super التي سنشرحها لاحقاً في هذا الدرس.

الكلمة extends في جافا

الكلمة extends تستخدم لجعل الكلاس يرث من كلاس آخر.


مكان وضع الكلمة extends

نضع الكلمة extends بعد إسم الكلاس, ثم نضع بعدها إسم الكلاس الذي نريد الوراثة منه.
الكود التالي يعني أن الكلاس B يرث من الكلاس A.

مثال

class A {

	  }

	  class B extends A {

	  } 
	

إنتبه: في حال كنت تحاول الوراثة من كلاس غير موجود سيظهر لك الخطأ التالي: java.lang.ExceptionInInitializerError



مثال

الآن لنفترض أننا قمنا بتعريف كلاس إسمه A يحتوي على متغير إسمه x و دالة إسمها printA(). بعدها قمنا بإنشاء كلاس جديد فارغ إسمه B و قلنا أنه يرث من الكلاس A. إذاً هذا يعني أن الكلاس B أصبح يملك نسخة من جميع المتغيرات و الدوال الموجودة في الكلاس A.

بعد إنشاء هذا الكلاس, سنقوم بإنشاء الكلاس Main لتجربته.

مثال

A.java
public class A {

	  public int x;

	  public void printA() {
	  System.out.println("I am from class A");
	  }

	  }
	

B.java
// A يرث المتغيرات و الدوال الموجودة في الكلاس B هنا قلنا أن الكلاس
	  public class B extends A {

	  // A سيحتوي المتغيرات و الدوال الموجودة في الكلاس B إذاً أي كائن من الكلاس

	  }
	

Main.java
public class Main {

	  public static void main(String[] args) {

	  // أم لا A لنتأكد إذا كان يحتوي على الأشياء الموجودة في الكلاس B هنا قمنا بإنشاء كائن من الكلاس
	  B b = new B();

	  // A من الكلاس B التي ورثها الكلاس printA() هنا قمنا باستدعاء الدالة
	  b.printA();

	  // أيضاً, يمكننا إعطائه قيمة و عرض قيمته x يملك متغير إسمه b و بما أن الكائن
	  b.x = 123;
	  System.out.println("x: " +b.x);

	  }

	  }
	

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

I am from class A
	  x: 123 
	

الكلمة super في جافا

الكلمة super تستخدم للأهداف التالية:

  • للتمييز بين الأشياء (المتغيرات و الدوال) الموجودة في الـ Superclass و Subclass في حال كانت الأسماء مستخدمة في كلا الكلاسَين.

  • لإستدعاء الـكونستركتور الموجود في الـ Superclass.

إذاً الكلمة super تستخدم لإستدعاء الأشياء الموجودة في الـ Superclass.



طريقة استخدام الكلمة super لإستدعاء متغير من الـ Superclass

نضع الكلمة super, بعدها نقطة, ثم نضع إسم المتغير الذي نريد إستدعائه من الـ Superclass.

super.variableName

شاهد المثال »



طريقة استخدام الكلمة super لإستدعاء دالة من الـ Superclass

نضع الكلمة super, بعدها نقطة, ثم نضع إسم الدالة التي نريد إستدعائها من الـ Superclass.

super.methodName();

شاهد المثال »


إنتبه

في حال قام الـ Subclass بتعريف دالة كانت أصلاً موجودة في الـ Superclass يجب كتابة الكلمة @Override قبلها مباشرةً, و هكذا سيفهم المترجم أن الـ Subclass قام بتعريف الدالة التي ورثها من الـ Superclass من جديد.



طريقة استخدامها عند استدعاء كونستركتور

يمكن استدعاء كونستركتور الـ Superclass من داخل كونستركتور الـ Subclass من خلال الكلمة super.

super()                    // عند استدعاء كونستركتور فارغ نكتب هكذا فقط

// أو هكذا

super( parameter List )    // عند استدعاء كونستركتور يحتوي على باراميترات, عليك تمرير قيم له.

في حال كان الـ Superclass يملك فقط كونستركتور لا يحتوي أي باراميترات (أي مثل كونستركتور إفتراضي), سيقوم المترجم باستدعائه بشكل تلقائي في الـ Subclass حتى لو لم تقم باستدعائه بنفسك.

شاهد الأمثلة »


و في حال كان الـ Superclass يملك أكثر من كونستركتور, ستكون مجبر على تعريف كونستركتور في الـ Subclass يستدعي أي كونستركتور من الكونستركتورات الموجودة في الـ Superclass.

شاهد الأمثلة »

أشكال الوراثة في جافا

في أي لغة برمجة, يوجد 3 أشكال أساسية للوراثة كما في الصورة التالية.

جافا لا تدعم تعدد الوراثة كما يوجد في بعض لغات البرمجة الأخرى, أي لا يمكن للكلاس الواحد الوراثة في نفس الوقت من أكثر من كلاس.
إذاً الكلاس الوحد لا يمكنه أن يفعل extends لأكثر من كلاس , بمعنى أن كل كلاس يمكنه وراثة كلاس واحد.

جافا تدعم تعدد الوراثة من خلال interface, أي من أجل الوراثة من أكثر من كلاس يجب إستخدام الكلمة interface بدلاً من class, و استخدام الكلمة implements بدلاً من extends ضمن شروط معينة. ستتعلم تعدد الوراثة في درس لاحق.


بالنسبة للوراثة المتتالية ( أو المتعددة المستويات ), دائماً آخر كلاس يرث جميع المتغيرات و الدوال الموجودة في الكلاسات الأعلى منه.


علاقة الكائنات مع بعضها في جافا

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

الآن سنقوم بتمثيل المطلوب في الصورة بلغة جافا.

مثال

// هنا قمنا بتعريف الكلاس الأساسي لجميع الحيوانات
	  class Animal { }

	  // هنا قمنا بتعريف فئات الحيوانات
	  class Mammals  extends Animal { }
	  class Reptiles extends Animal { }
	  class Birds    extends Animal { }
	  class Aquatic  extends Animal { }

	  // هنا قمنا بتعريف 4 حيوانات مع وضع كل حيوان ضمن فئته
	  class Dog      extends Mammals { }
	  class Snack    extends Reptiles { }
	  class Parrot   extends Birds { }
	  class Dolphin  extends Aquatic { }
	

إذاً هنا يمكننا قراءة الكود كالتالي:

  • Dog يعتبر من الـ Mammals و يعتبر Animal أيضاً.

  • Snack يعتبر من الـ Reptiles و يعتبر Animal أيضاً.

  • Parrot يعتبر من الـ Birds و يعتبر Animal أيضاً.

  • Dolphin يعتبر من الـ Aquatic و يعتبر Animal أيضاً.

العامل instanceof في جافا

العامل instanceof يستخدم لمعرفة إذا كان الكائن ينتمي إلى كلاس معين أم لا.
يرجع true في حال كان الكائن ينتمي لكلاس معين, غير ذلك يرجع false.


مثال

الآن سنقوم بكتابة الكود السابق و استخدام العامل instanceof لمعرفة الكلاسات التي ينتمي إليها الكائن.

ملاحظة: هنا قمنا بتعريف جميع الكلاسات كـ private وراء بعضهم في نفس ملف الجافا لأن جافا تسمح بذلك. لكننا لا ننصح باستخدام هذا الأسلوب في البرامج العادية.
كما أننا سنستخدم العامل instanceof في دروس لاحقة.

مثال

Main.java
// هنا قمنا بتعريف الكلاس الأساسي لجميع الحيوانات
	  class Animal { }

	  // هنا قمنا بتعريف فئات الحيوانات
	  class Mammals  extends Animal { }
	  class Reptiles extends Animal { }
	  class Birds    extends Animal { }
	  class Aquatic  extends Animal { }

	  // هنا قمنا بتعريف 4 حيوانات مع وضع كل حيوان ضمن فئته
	  class Dog      extends Mammals { }
	  class Snack    extends Reptiles { }
	  class Parrot   extends Birds { }
	  class Dolphin  extends Aquatic { }


	  public class Main {

	  public static void main(String[] args) {

	  // Dog هنا قمنا بإنشاء كائن من الكلاس
	  Dog dog1 = new Dog();

	  // dog1 هنا قمنا باختبار الكلاسات التي ينتمي إليها الكائن
	  System.out.println( dog1 instanceof Dog);
	  System.out.println( dog1 instanceof Animal);

	  }

	  }
	

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

true
	  true
	

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

في جافا, يوجد مئات الكلاسات الجاهزة التي تم بناءها بشكل هرمي كما في الصورة التالية.


جميع الكلاسات في جافا ترث بشكل تلقائي من الكلاس Object لأنه فعلياً يأتي في رأس الهرم و بالتالي فوق الجميع.
إذاً الكلاس Object هو أعلى Superclass في جافا.

و إذا لاحظت في الدروس السابقة أن أي كلاس جديد كنا نستخدمه يحتوي على الدوال equals(), hashcode(), toString() إلخ..
سبب وجود هذه الدوال في كل كلاس كنا نستخدمه أنه ورثوهم من الكلاس Object.

مثال حول طريقة إستدعاء متغير من الـ Superclass

لنفترض أننا قمنا بتعريف كلاس إسمه A يحتوي على متغير إسمه x.
بعدها قمنا بإنشاء كلاس إسمه B يرث من الكلاس A و يحتوي على متغير إسمه x, و دالة إسمها printBoth() تطبع قيمة x الموجود في A و قيمة x الموجود في B بطريقتين.

بعدها سنقوم بإنشاء الكلاس Main لتجربة الكود.

A.java
                    public class A {

	  public int x = 5;

	  }
	

B.java
                    public class B extends A {                                   // A يرث من الكلاس B هنا قلنا أن الكلاس

	  public int x = 20;                                       // مع وضع قيمة مختلفة له A هنا قمنا بتعريف نفس المتغير الموجود في الكلاس

	  public void printBoth() {                                // عند استدعاء هذه الدالة سيتم عرض الأشياء التالية
	  System.out.println("x in B contain: " +x);           // B الموجودة في الكلاس x هنا سيتم عرض قيمة الـ
	  System.out.println("x in B contain: " +this.x);      // B الموجودة في الكلاس x هنا سيتم عرض قيمة الـ
	  System.out.println("x in A contain: " +super.x);     // A الموجودة في الكلاس x هنا سيتم عرض قيمة الـ
	  }

	  }
	

Main.java
                    public class Main {

	  public static void main(String[] args) {

	  B b = new B();     // منه printBoth() من أجل إستدعاء الدالة B هنا قمنا بإنشاء كائن من الكلاس

	  b.printBoth();     // هنا قمنا باستدعائها

	  }

	  }
	

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

                    x in B contain: 20
	  x in B contain: 20
	  x in A contain: 5 
	

مثال حول طريقة إستدعاء دالة من الـ Superclass

تذكر

لا تنسى وضع الكلمة @Override قبل إسم الدالة التي ورثها الـ Subclass في الأصل من الـ Superclass و لكنه قام بتعريفها من جديد.


الآن لنفترض أننا قمنا بتعريف كلاس إسمه A يحتوي على دالة إسمه print().
بعدها قمنا بإنشاء كلاس إسمه B يرث من الكلاس A و يحتوي على دالة إسمها print() أيضاً, بالإضافة إلى دالة إسمها printBoth() تستدعي الدالة print() الموجودة في A و تستدعي الدالة print() الموجودة في B بطريقتين.

بعدها سنقوم بإنشاء الكلاس Main لتجربة الكود.

A.java
                      public class A {

	  public void print() {
	  System.out.println("This is print() method from the class A");
	  }

	  }
	

B.java
                      public class B extends A {          // A يرث من الكلاس B هنا قلنا أن الكلاس

	  // قبلها, مع وضع جملة مختلفة في دالة الطباعة @Override لذلك وضعنا A هنا قمنا بتعريف نفس الدالة الموجودة في الكلاس
	  @Override
	  public void print() {
	  System.out.println("This is print() method from the class B");
	  }

	  // هنا قمنا بتعريف دالة مهمتها فقط إستدعاء الدوال الموجودة بداخلها
	  public void printBoth() {
	  print();               // B الموجودة في الكلاس print() هنا سيتم إستدعاء الدالة
	  this.print();          // B الموجودة في الكلاس print() هنا سيتم إستدعاء الدالة
	  super.print();         // A الموجودة في الكلاس print() هنا سيتم إستدعاء الدالة
	  }

	  }
	

Main.java
                      public class Main {

	  public static void main(String[] args) {

	  B b = new B();     // منه printBoth() من أجل إستدعاء الدالة B هنا قمنا بإنشاء كائن من الكلاس

	  b.printBoth();     // هنا قمنا باستدعائها

	  }

	  }
	

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

                      This is print() method from the class B
	  This is print() method from the class B
	  This is print() method from the class A 
	

أمثلة حول طريقة إستدعاء كونستركتور لا يحتوي باراميترات من الـ Superclass

في المثال التالي قمنا بتعريف كلاس إسمه A يحتوي على متغيرين x و y بالإضافة إلى كونستركتور لا يقبل أي باراميتر و مهمته بتوليد قيم لهما فقط.
بعدها قمنا بإنشاء كلاس إسمه B يرث من الكلاس A.

بعدها سنقوم بإنشاء الكلاس Main لتجربة الكود.

المثال الأول

A.java
                    public class A {

	  public int x;
	  public int y;

	  // A هنا قمنا بتعريف الكونستركتور الإفتراضي للكلاس
	  // سيتم تنفيذه بشكل تلقائي في أي كلاس يرث منه .A و بما أنه لا يوجد غيره في الكلاس
	  public A() {
	  x = 50;
	  y = 100;
	  }

	  }
	

B.java
                    public class B extends A {          // A يرث من الكلاس B هنا قلنا أن الكلاس

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

	  }
	

Main.java
                    public class Main {

	  public static void main(String[] args) {

	  // A من أجل عرض قيم المتغيرات التي ورثها من الكلاس B هنا قمنا بإنشاء كائن من الكلاس
	  B b = new B();

	  System.out.println("x: " + b.x);
	  System.out.println("y: " + b.y);

	  }

	  }
	

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

                    x: 50
	  y: 100 
	



في المثال التالي قمنا بكتابة نفس الكود السابق مع إستدعاء كونستركتور الكلاس A في كونستركتور الكلاس B.
تذكر أنه لا يوجد داعي لكتابة هذا الكود لأن مترجم لغة جافا يفعل ذلك بشكل تلقائي عنك.

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

A.java
                    public class A {

	  public int x;
	  public int y;

	  // A هنا قمنا بتعريف الكونستركتور الإفتراضي للكلاس
	  // سيتم تنفيذه بشكل تلقائي في أي كلاس يرث منه .A و بما أنه لا يوجد غيره في الكلاس
	  public A() {
	  x = 50;
	  y = 100;
	  }

	  }
	

B.java
                    public class B extends A {    // A يرث من الكلاس B هنا قلنا أن الكلاس

	  // نفس الشرح السابق تماماً, لكن هنا يمكنك القول أننا ذكرنا ما حدث بتفصيل
	  public B() {              // B عند استخدام هذا الكونستركتور لإنشاء كائن من الكلاس
	  super();              // A سيتم إستدعاء كونستركتور الكلاس
	  }

	  }
	

Main.java
                    public class Main {

	  public static void main(String[] args) {

	  // A من أجل عرض قيم المتغيرات التي ورثها من الكلاس B هنا قمنا بإنشاء كائن من الكلاس
	  B b = new B();

	  System.out.println("x: " + b.x);
	  System.out.println("y: " + b.y);

	  }

	  }
	

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

                    x: 50
	  y: 100 
	



في المثال التالي قمنا بكتابة نفس الكود السابق مع تعريف متغير جديد في الكلاس B إسمه z و إعطائه قيمة في الكونستركتور, و تغيير قيمة المتغير x في كونستركتور الكلاس B.
عند تجربة الكود سنقوم بعرض قيم المتغيرات الموجودة في A و B.

الهدف الحقيقي هنا إيصال فكرة أن الـ Subclass يمكنه إستخدام الأشياء التي ورثها من الـ Superclass كما يشاء.

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

A.java
                    public class A {

	  public int x;
	  public int y;

	  // A هنا قمنا بتعريف الكونستركتور الإفتراضي للكلاس
	  // سيتم تنفيذه بشكل تلقائي في أي كلاس يرث منه .A و بما أنه لا يوجد غيره في الكلاس
	  public A() {
	  x = 50;
	  y = 100;
	  }

	  }
	

B.java
                    public class B extends A {    // A يرث من الكلاس B هنا قلنا أن الكلاس

	  public int z;             // z هنا قمنا بتعريف المتغير

	  public B() {              // B عند استخدام هذا الكونستركتور لإنشاء كائن من الكلاس
	  super();              // A سيتم إستدعاء كونستركتور الكلاس
	  z = 123;              // z و سيتم إعطاء قيمة للمتغير
	  x = 9;                // A بالقيمة 9, مع الملاحظة أنها ستبقى 50 في أي كائن من الكلاس B في أي كائن من الكلاس x هنا سيتم تبديل قيمة المتغير
	  }

	  }
	

Main.java
                    public class Main {

	  public static void main(String[] args) {

	  // A من أجل عرض قيم المتغيرات التي ورثها من الكلاس B هنا قمنا بإنشاء كائن من الكلاس
	  B b = new B();

	  System.out.println("In class B we have:");
	  System.out.println("x: " + b.x);
	  System.out.println("y: " + b.y);
	  System.out.println("z: " + b.z);

	  System.out.println();

	  // من أجل التأكد من أن قيم متغيراته لا تتأثر إذا تم تغيير نفس المتغيرات في أي كلاس يرث منه A هنا قمنا بإنشاء كائن من الكلاس
	  A a = new A();

	  System.out.println("In class A we have:");
	  System.out.println("x: " + a.x);   // B الموجود في الكلاس x مختلفة عن قيمة المتغير A الموجود في الكلاس x لاحظ كيف أن قيمة المتغير
	  System.out.println("y: " + a.y);

	  }

	  }
	

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

                    In class B we have:
	  x: 9
	  y: 100
	  z: 123

	  In class A we have:
	  x: 50
	  y: 100
	

أمثلة حول وجود أكثر من كونستركتور في الـ Superclass

الآن سنقوم بتقسيم الأمثلة حسب الحالة التي قد نصادفها.


الحالة الأولى

في حال كان الـ Superclass يملك 2 كونستركتور, الأول لا يحتوي أي باراميترات و الثاني يحتوي باراميترات.
هنا يمكنك عدم تعريف كونستركتور في الـ Subclass, أو تعريف واحد فارغ لكي يستدعي الكونستركتور الإفتراضي الموجود في الـ Subclass.

في هذا المثال قمنا بتعريف كلاس إسمه A يحتوي على متغيرين x و y بالإضافة إلى 2 كونستركتور, الأول لا يقبل أي باراميتر و مهمته بتوليد قيم لهما فقط و الثاني مهمته يتيح لك تمرير قيم للمتغيرات x و y مباشرةً عند إنشاء كائن.
بعدها قمنا بإنشاء كلاس إسمه B يرث من الكلاس A.

بعدها سنقوم بإنشاء الكلاس Main لتجربة الكود.

المثال الأول

A.java
                    public class A {

	  public int x;
	  public int y;

	  // عند استدعائه y و x هنا قمنا بتعريف كونستركتور لا يأخذ أي باراميتر و مهمته فقط إعطاء قيم أولية للمتغيرات
	  public A() {
	  x = 50;
	  y = 100;
	  }

	  // عند استدعائه y و x هنا قمنا بتعريف كونستركتور يسمح بتمرير قيم أولية للمتغيرات
	  public A(int x, int y) {
	  this.x = x;
	  this.y = y;
	  }

	  }
	

B.java
                    public class B extends A {          // A يرث من الكلاس B هنا قلنا أن الكلاس

	  // هنا لا داعي لتعريف كونستركتور جديد
	  // حتى و إن لم نقم باستدعائه A هنا سيتم إستدعاء الكونستركتور الإفتراضي ( الذي لا يحتوي أي بارميتر ) الموجود في الكلاس

	  }
	

Main.java
                    public class Main {

	  public static void main(String[] args) {

	  // B باستخدام الكونستركتور الفارغ الموجود بشكل تلقائي في الكلاس B هنا قمنا بإنشاء كائن من الكلاس
	  B b = new B();

	  System.out.println("x: " + b.x);
	  System.out.println("y: " + b.y);

	  }

	  }
	

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

                    x: 50
	  y: 100 
	



الحالة الثانية

في حال كان الـ Superclass يملك كونستركتور أو أكثر, لكنه لا يملك على كونستركتور لا يحتوي باراميترات.
هنا أنت مجبر على تعريف كونستركتور في الـ Subclass, يستدعي أي كونستركتور من الـ constructors الموجودين في الـ Superclass.

ملاحظة: عدد الباراميترات التي تضعها في كونستركتور الـ Subclass غير مهم حتى يعمل الكود بشكل سليم. المهم هنا استدعاء أي كونستركتور موجود في الـ Superclass بداخل أي كونستركتور ستقوم بتعريفه في الـ Subclass.

في هذا المثال قمنا بتعريف كلاس إسمه A يحتوي على متغيرين x و y بالإضافة إلى 2 كونستركتور, الأول لا يقبل أي باراميتر و مهمته بتوليد قيم لهما فقط و الثاني مهمته يتيح لك تمرير قيم للمتغيرات x و y مباشرةً عند إنشاء كائن.
بعدها قمنا بإنشاء كلاس إسمه B يرث من الكلاس A.

بعدها سنقوم بإنشاء الكلاس Main لتجربة الكود.

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

A.java
                    public class A {

	  public int x;
	  public int y;

	  // عند استدعائه y و x يحتوي على كونستركتور يسمح بتمرير قيم أولية للمتغيرات A الكلاس
	  // لأنه لا يوجد كونستركتور لا يحتوي على باراميترات Subclass هنا يجب استدعاء هذا الكونستركتور في أي
	  public A(int x, int y) {
	  this.x = x;
	  this.y = y;
	  }

	  }
	

B.java
                    public class B extends A {          // A يرث من الكلاس B هنا قلنا أن الكلاس

	  // A هنا يجب تعريف كونستركتور واحد على الأقل يستدعي الكونستركتور الموجود في الكلاس

	  // Superclass A هنا قمنا بتعريف كونستركتور يمرر القيمتين 123 و 456 في كونستركتور الـ
	  public B() {
	  super(123, 456);
	  }

	  // Superclass A هنا قمنا بتعريف كونستركتور نمرر له قيمتين عند استدعائه, فيقوم بدوره بتمريرهما في كونستركتور الـ
	  public B(int p1, int p2) {
	  super(p1, p2);
	  }

	  }
	

Main.java
                    public class Main {

	  public static void main(String[] args) {

	  // الذي لا يأخذ باراميترات B باستخدام كونستركتور الكلاس B هنا قمنا بإنشاء كائن من الكلاس
	  B b1 = new B();
	  System.out.println("Here the constructor generate these values for the object b1:");
	  System.out.println("x: " + b1.x);
	  System.out.println("y: " + b1.y);

	  System.out.println();

	  // الذي يأخذ 2 باراميتر B باستخدام كونستركتور الكلاس B هنا قمنا بإنشاء كائن من الكلاس
	  B b2 = new B(47, 13);
	  System.out.println("Here the constructor generate these values for the object b2:");
	  System.out.println("x: " + b2.x);
	  System.out.println("y: " + b2.y);

	  }

	  }
	

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

                    Here the constructor generate these values for the object b1:
	  x: 123
	  y: 456

	  Here the constructor generate these values for the object b2:
	  x: 47
	  y: 13