GagorAcadmey

تعلم برمجة تطبيقات الاندرويد من الصفر حتي الاحتراف

آخر المواضيع

الاثنين، 3 سبتمبر 2018

Polymorphism in java

مفهوم الـ Polymorphism

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

تحقيق البوليمورفيزم

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

Polymorphic Array

في دروس سابقة رأيت أنه يمكنك تعريف مصفوفة من أي نوع تريده, فمثلاً يمكنك تعريف مصفوفة من النوع int, double أو String إلخ..
  1. في حال قمت بتعريف مصفوفة نوعها int, عندها يمكنك تخزين قيمة نوعها int في كل عنصر موجود فيها.

  2. في حال قمت بتعريف مصفوفة نوعها String, عندها يمكنك تخزين قيمة نوعها String في كل عنصر موجود فيها.

خلاصة: في جافا, يمكنك تعريف مصفوفة من أي نوع تريده.
Polymorphic Array: تعني تطبيق مبدأ البوليمورفيزم من خلال مصفوفة.
و المقصود هنا أنه يمكنك تعريف مصفوفة نوعها كائن و تخزين كائنات من نفس نوعها فيها.

في المثال التالي قمنا بإنشاء كلاس إسمه A يحتوي على متغير إسمه x و دالة إسمها printX().
بعدها قمنا بإنشاء كلاس آخر إسمه Test.
بداخل الكلاس Test قمنا بإنشاء 5 كائنات من الكلاس A, ثم قمنا بتعريف مصفوفة إسمها list نوعها a و وضعنا فيها الكائنات التي أنشأناها من الكلاس A.
كل كائن وضعناه فيها يعتبر عنصر من عناصرها, و بالتالي يمكننا الوصول لهم أيضاً منها من خلال أرقام الـ index إن أردنا.
مثال: list[0], list[1], list[2] إلخ..

المثال الأول

A.java
class A { // A هنا قمنا بتعريف كلاس إسمه
public int x;
public void printX(){
System.out.println("x contain: " + x);
      }
}
Test.java
public class Test {
public static void main(String[] args){
// A أي 5 كائنات نوعهم ,A هنا قمنا بتعريف 5 كائنات من الكلاس
A a1 = new A();
A a2 = new A();
A a3 = new A();
A a4 = new A();
A a5 = new A();
// فيها A ثم قمنا بتخزين جميع الكائنات المشتقة من ,A هنا قمنا بإنشاء مصفوفة نوعها
A[] list = { a1, a2, a3, a4, a5 };
//list المخزن كثالث عنصر في المصفوفة a3 الموجود في الكائن x هنا قمنا بإعطاء قيمة للمتغير
list[2].x = 20;
//list[2] الموجودة في العنصر x سترجع قيمة المتغير printX() لاحظ أن الدالة
a3.printX();
//a3 الموجودة في العنصر x سترجع قيمة المتغير printX() و لاحظ أن الدالة
list[2].printX();
   }
}
سنحصل على النتيجة التالية عند التشغيل.
x contain: 20
x contain: 20


إذاً يمكنك بناء مصفوفة نوعها كلاس, و تخزين كائنات من نفس النوع فيها كما رأيت في المثال السابق.
في المثال التالي سترى أنه يمكنك تخزين كائنات مشتقة من نفس نوع المصفوفة فيها أيضاً و هذا من مبادئ الـ Upcasting و تطبيق لمبدأ الـ Polymorphic Array.

في المثال التالي قمنا بإنشاء كلاس إسمه A و نوعه abstract, و يحتوي على دالة إسمها print() و نوعها abstract أيضاً.
بعدها قمنا بإنشاء إثنين كلاس B و C يرثان من A. بعدها قمنا بإنشاء كلاس آخر إسمه Test و الذي سنطبق فيه مبدأ الـ Polymorphic Array.
بداخل الكلاس Test قمنا بإنشاء كائن من الكلاس B و كائن من الكلاس C, ثم قمنا بتعريف مصفوفة إسمها list و نوعها a, و وضعنا فيها الكائنات التي ترث من الكلاس A.

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

A.java
package polymorphism;
public abstract class A {//إذاً لا يمكن إنشاء كائنات منه ,Abstract نوعه A الكلاس
public abstract void print();//abstract لهذه الدالة لأن نوعها Override يجب أن يفعل A أي كلاس سيرث من الكلاس
}

B.java
package polymorphism;
public class B extends A { // A يرث من الكلاس B هنا قلنا أن الكلاس
@Override
public void print() {
System.out.println("class B"); // إذا قمت باستدعاء هذه الدالة من هذا الكلاس ستعرض هذه الجملة
      }
}

C.java
package polymorphism;
public class C extends A { // A يرث من الكلاس C هنا قلنا أن الكلاس
@Override
public void print() {
System.out.println("class C"); // إذا قمت باستدعاء هذه الدالة من هذا الكلاس ستعرض هذه الجملة
       }
}

Test.java
package polymorphism;
public class Test{
public static void main(String[] args){
A b = new B();// B ثم قمنا بتحديد نوعه ككائن من A هنا قمنا بإنشاء كائن من الكلاس
A c = new C();// C ثم قمنا بتحديد نوعه ككائن من A هنا قمنا بإنشاء كائن من الكلاس
A[] list = new A[2];// تتألف من عنصرين فقط A هنا قمنا بإنشاء مصفوفة نوعها
// فيها A سنخزن الكائنات المشتقة من الكلاس
list[0] = b;// list[0] في أول عنصر في المصفوفة b هنا قمنا بتخزين الكائن
list[1] = c;// list[1] في ثاني عنصر في المصفوفة c هنا قمنا بتخزين الكائن
for(int i=0; i<list.length; i++){// هنا قمنا ببناء حلقة للمرور على جميع عناصر المصفوفة
list[i].print();// الخاصة بكل عنصر print() هنا سيتم إستدعاء الدالة
      }// على إختلاف كل كائن موجود في المصفوفة print() إذاً هنا سيختلف أداء الدالة
   }
}

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

Polymorphic Argument

Polymorphic Argument تعني بناء دالة تنفذ أوامر مختلفة على حسب الكائن الذي يمرر لها كـ argument.

الآن سنقوم بتعريف كلاس إسمه Shape و نوعه abstract, هذا الكلاس سنعتبره كلاس أساسي لجميع الأشكال الهندسية, أي سيكون Superclass لأي كلاس يمثل أحد الأشكال الهندسية. Shape يحتوي على دالة إسمها shapeForm() و نوعها abstract أيضاً, هذه الدالة فكرتها طباعة الشكل الهندسي للكائن الذي يقوم باستدعائها.
بعدها سنقوم بتعريف أربع كلاسات Square, Rectangle, Triangle و Circle.
كل كلاس منهم سيمثل شكل هندسي معين, إذاً يجب أن يرثوا جميعاً من الكلاس Shape, و يجب أن يفعلوا Override للدالة shapeForm() بهدف جعلها ترسم الشكل المطلوب من كل كلاس.
بعدها سنقوم بتعريف كلاس إسمه Drawer و الفكرة منه بناء كلاس لرسم أي كائن مشتق من Shape.
بعد إنشاء جميع هذه الكلاسات, سنقوم بإنشاء الكلاس Test لتجربة الكود.

مثال

Shape.java
package polymorphism;
public abstract class Shape{
// لها حتى تطبع الشكل المناسب له Override على كل كائن يمثل شكل هندسي أن يفعل
public abstract void shapeForm();
 }

Square.java
package polymorphism;
public class Square extends Shape {
// إذا قمت باستدعاء هذه الدالة من هذا الكائن, ستعرض لك شكل يشبه المربع
@Override
public void shapeForm() {
System.out.println("* * * *\n* * * *\n* * * *\n");
   }
}

Rectangle.java
package polymorphism;
public class Rectangle extends Shape{
// إذا قمت باستدعاء هذه الدالة من هذا الكائن, ستعرض لك شكل يشبه المربع
@Override
public void shapeForm() {
System.out.println("* * * * * *\n* * * * * *\n* * * * * *\n");
   }
}

Triangle.java
package polymorphism;
public class Triangle extends Shape{
// إذا قمت باستدعاء هذه الدالة من هذا الكائن, ستعرض لك شكل يشبه المثلث
@Override
public void shapeForm() {
System.out.println(" *\n * *\n * * *\n * * * *\n* * * * *\n"); 
  }
}

Drawer.java
package polymorphism;
public class Drawer {
public void draw(Shape s) {// Shape عند إستدعاء هذه الدالة يجب ان نمرر لها أي كائن مشتق من الكلاس
s.shapeForm();// الموجودة في الكائن الذي قام باستدعاءها shapeForm() هنا سيتم استدعاء الدالة
     }
}

Test.java
package polymorphism;
public class Test {
public static void main(String[] args){
//هنا كل كائن سيمثل شكل هندسي معين
Shape s = new Square();//Square و حددنا أن نوعه Shape هنا قمنا بإنشاء كائن من
Shape r = new Rectangle(); //Rectangle و حددنا أن نوعه Shape هنا قمنا بإنشاء كائن من
Shape t = new Triangle(); //Triangle و حددنا أن نوعه Shape هنا قمنا بإنشاء كائن من
Drawer drawer = new Drawer();//الموجودة فيه draw() حتى نستطيع استخدام الدالة drawer هنا قمنا بإنشاء كائن من
//لعرض شكل كل كائن draw() هنا قمنا باستدعاء الدالة
drawer.draw(s);//Square المعرفة في الكلاس shapeForm() سيتم إستدعاء الدالة ,Square نوعه s بما أن الكائن
drawer.draw(r); //Rectangle المعرفة في الكلاس shapeForm() سيتم إستدعاء الدالة ,Rectangle نوعه r بما أن الكائن
drawer.draw(t); //Triangle المعرفة في الكلاس shapeForm() سيتم إستدعاء الدالة ,Triangle نوعه t بما أن الكائن
   }
}

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

* * * * * *
* * * * * *
* * * * * *

*
* *
* * *
* * * *
* * * * *

العامل instanceof في Polymorphism

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

في المثال التالي قمنا بإنشاء كلاس إسمه A.
بعدها قمنا بإنشاء إثنين كلاس B و C يرثان من A.
بعدها قمنا بإنشاء كلاس آخر إسمه Test.
بداخل الكلاس Test قمنا بتعريف دالة إسمها check() تأخذ كائن مشتق من A كـ argument فتعرض لنا إسم الكلاس الذي إشتق منه الكائن.
بعدها قمنا بإنشاء كائن من الكلاس B و كائن من الكلاس C, ثم قمنا بتمريرهما في الدالة check().

مثال

Person.java
package polymorphism;
public class A {
}

B.java
package polymorphism;
public class B extends A {
}

C.java
package polymorphism;
public class C extends A {
}

Test.java
package polymorphism;
public class Test {
public static void main(String[] args) {
A b = new B();// B و حددنا أن نوعه A هنا قمنا بإنشاء كائن من
A c = new C();// C و حددنا أن نوعه A هنا قمنا بإنشاء كائن من
check(b);// لمعرفة إسم الكلاس المشتق منه check() في الدالة b هنا قمنا بتمرير الكائن
check(c); // لمعرفة إسم الكلاس المشتق منه check() في الدالة c هنا قمنا بتمرير الكائن
     }
static void check (A obj) {
if(obj instanceof B)// سيتم تنفيذ أمر الطباعة الموجود فيها B كائن من الكلاس obj في حال كان الـ
{
System.out.println("This is an object from the class B");
      }
else if(obj instanceof C) // سيتم تنفيذ أمر الطباعة الموجود فيها C كائن من الكلاس obj في حال كان الـ
{
System.out.println("This is an object from the class C");
      }
   }
}
سنحصل على النتيجة التالية عند التشغيل.
This is an object from the class B
This is an object from the class C

Type of Polymorphism

  1. Static Polymorphism also known as compile time polymorphism

  2. Dynamic Polymorphism also known as runtime polymorphism

Static Polymorphism

يعرف تعدد الاشكال الذي يتم تنفيذه خلال وقت المجمع compiler time بتعدد الاشكال الثابت ومن أمثلة هذا النوع هو دوال التحميل الزائدة Method Overloading
class Calculator {
    int add(int a, int b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }
}

public class Main {
    public static void main(String args[]) {
        Calculator obj = new Calculator();
        System.out.println(obj.add(50, 20));
        System.out.println(obj.add(30, 20, 30));
    }
}
سنحصل على النتيجة التالية عند التشغيل.
70
80

Dynamic Polymorphism

تعدد الاشكال الديناميكي هو عملية شبيه جدا بعملية إعادة تهيئة الدوال Overriding خلال وقت التشغيل runtime
class ABC{
   public void myMethod(){
      System.out.println("Overridden Method");
   }
}
public class Main extends ABC{

   public void myMethod(){
      System.out.println("Overriding Method");
   }
   public static void main(String args[]){
      ABC obj = new Main();
      obj.myMethod();
   }
}
سنحصل على النتيجة التالية عند التشغيل.
Overriding Method

ليست هناك تعليقات:

إرسال تعليق

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

صفحتنا علي الفيسبوك

التسميات

المتواجدين حاليا