شما می توانید با ارسال ایمیل خود ، بصورت رایگان مشترک شده و از بروزسانی مطلع شوید.

ایمیل خود را وارد کنید:

اوراکل (ADF(Application Development Framework یک چارچوب(Framework)  کلی می باشد که برروی استانداردهای Java EE و تکنولوژی های Open Source جهت سادگی و پیاده سازی سریع تر برنامه های Java EE ایجاد شده است که کاملا توسعه پذیر و قابل تنظیم بوسیله افزودن یا اصلاح کتابخانه ها می باشد. ADF وظایف را از طریق ایجاد سرویس […]

CardLayout پنجره ای را در نظر بگیرید که شامل چندین پنل می باشد که در یک زمان فقط یکی از این پنل ها قابل مشاهده می باشد،با استفاده از کلاس java.awt.CardLayout شما می توانید کامپوننتی را ایجاد کنید که فقط یکی از این پنل ها را در یک زمان نمایش دهد، مانند شکل زیر: زمانی […]

اطلاعات سخت افزاری CPU اطلاعات CPU شامل جزئیاتی  مثل معماری ، نام سازنده ، مدل ، تعداد هسته ها ، سرعت هرکدام از هسته ها و غیره است. برای دسترسی به چنین جزئیاتی درباره سخت افزار CPU در لینوکس، تعداد بسیار اندکی کامند برای این منظور وجود دارد که ما در اینجا بطور مختصر تعدادی […]

چند ریختی یا Polymorphism

چند ریختی از طریق یک مثال برای درک آسان تر است.بیایید به کلاس های Person, Employee و Contractor از زاویه های مختلف نگاه کنیم.

به کلاسهای Employee و Contractor در زیر توجه فرمائید:

مثال: کلاس Employee

public class Employee extends Person{
public Employee(String name){
super(name);
}
public boolean increasePay(int percent) {
System.out.println("Increasing salary by " +
percent + "%. "+ getName());
return true;
         }
}

مثال : کلاس Contractor

public class Contractor extends Person {
public Contractor(String name){
super(name);
}
public boolean increasePay(int percent) {
if(percent < INCREASE_CAP){
System.out.println("Increasing hourly rate by " +
percent + "%. "+ getName());
return true;
} else {
System.out.println("Sorry, can’t increase hourly rate by more
than " + INCREASE_CAP + "%. "+ getName());
return false;
         }
     }
}

هر دوکلاس Employee و  Contractor از کلاس پایه یعنی Person ارث برده شده اند.بجای داشتن متدهای مختلف برای افزایش حقوق مبنی بر نوع کارکنان، ما یک رفتار چندریختی به متد()increasePay دادیم،که منطق کسب و کارهای مختلف را بسته به نوع شی  اعمال می کند.

هرچند که بنظر می رسد که اگر ما در حال فراخوانی همان متد()promote  بروی شی ای از آرایه Workers هستیم اما اینطور نیست.از آنجاییکه نوع شی واقعی در حین اجرا ارزیابی شده ،حقوق طبق  این پیاده سازی شی از متد ()increasePay بدرستی افزایش یافته است.این عمل چندریختی یا polymorphism است.

حال به کلاس TestPayIncrease2 توجه بفرمائید:

public class TestPayIncrease2 {
public static void main(String[] args) {
Person workers[] = new Person[3];
workers[0] = new Employee("Saeed");
workers[1] = new Contractor("Amir");
workers[2] = new Employee("Mohammad");
for (Person p: workers){
p.promote(30);
                            }
             }
}

حلقه For در کلاس TestPayIncrease2 همانطور باقی خواهد ماند حتی اگر ما انواع دیگری از کارکنان  ارث برده شده از کلاس Person را اضافه کنیم.برای مثال،برای اضافه کردن یک لیست جدید از کارگر__یک پیمانکار خارجی__ما بایستی یک کلاس بنام ForeignContractor که از کلاس Person مشتق شده است را ایجاد کنیم و متد ()increasePay را انجا پیاده سازی کنیم.

کلاس TestPayIncrease2 بررسی نوع واقعی فرزندان کلاس Person  را در حین اجرا نگه خواهد داشت و پیاده سازی مناسبی از متد ()increasePay را فراخوانی می کند.

اگرچه آرایه workers از نوع کلاس Person تعریف شده است، آن ساکن شده است بوسیله اشیایی که واسط Payble را پیاده سازی می کنند.

بجای cast کردن اشیا از این آرایه  به کلاسهای Employee یا  Contractor ،شما می توانید این اشیا را به واسط Payble cast کنید و متد ()increasePay را بدون نگرانی از اینکه پرسنل جاری کارمند است یا پیمانکار فراخوانی می کنید.

کلاسTestPayIncreasePoly را مشاهده کنید:

public class TestPayInceasePoly {
public static void main(String[] args) {
Person workers[] = new Person[3];
workers[0] = new Employee("Saeed");
workers[1] = new Contractor("Amir");
workers[2] = new Employee("Mohammad");
for (Person p: workers){
((Payable)p).increasePay(30);
                    }
           }
}

توجه داشته باشید که متغییر p به اولین payble ،cast شده است و فقط بعداز متد ()increasePay می تواند فراخوانی شده باشد.برای اجرای پی در پی این عملگرها این کد با پرانتزها بسته شده است. Eclipse IDE دارای راهنمای حساس نسبت به محیط می باشد__یعنی  زمانی که شما  یک نقطه بعداز پرانتزها تایپ می کنید به شما متد ()increasePay را از لیست متدهای موجود نمایش می دهد.

راه حل دیگری که نیاز cast به Payble را بین خواهد برد داشتن کلاس Person که واسط Payble را پیاده سازی می کند می باشد.در این صورت حلقه for مثال  قبلی بصورت زیر خواهد بود:

for (Payable p: workers){
increasePay(30);
}

واسط ها در مقابل کلاس های انتزاعی(abstract)

سوال بعدی اینکه شما چه زمانی باید از واسط ها و چه زمانی باید از کلاس های Abstract استفاده کنید.اگر ۲ یا بیشتر کلاس ها قابلیت های مشترکی داشته باشند،اما بعضی از متدها بایستی متفاوت پیاده سازی شده باشند،شما می توانید یک کلاس پدر Abstract مشترک و همچنین تعدادی کلاس فرزند که این قابلیت های مشترک را اگر احتیاج دارند به ارث ببرند  پیاده سازی کنید.آن متدهایی که کلاس های فرزند بایستی بصورت متفاوت پیاده سازی کنند را در کلاس پدر بصورت abstract تعریف می کنید و این متدها را در کلاس فرزند پیاده سازی می کنید.

اگر وقتی چندین کلاس قابلیت های مشترکی ندارند ولی به رفتارهای مشترکی احتیاج دارند،شما دیگه یک کلاس پدر مشترک ایجاد نمی کنید بلکه  آنها را در یک واسط که رفتارهای در خواست شده را تعریف می کند پیاده سازی می کنید.

واسط ها و کلاس های abstract در تضمین اینکه متدهای درخواست شده طبق خط تعریف متدهای درخواست شده  پیاده سازی خواهند شد شبیه هم هستند،اما فرق آنها دراین است که برنامه چگونه طراحی شده است درحالی که کلاس های abstract از شما ارائه یک کلاس پدر مشترک را برای کلاس ها درخواست می کند، اما واسط ها قادر به آن نیستند.

واسط ها می توانند تنها انتخاب شما باشند اگر یک کلاس قبلا یک کلاس پدر دارد که نمی تواند تغییرکند.جاوا از ارث بری چندگانه حمایت نمی کند__یعنی یک کلاس فقط یک کلاس پدر می تواند داشته باشد.برای مثال برای نوشتن اپلت های جاوا کلاس شما بایستی از کلاس Applet ارث ببرد یا در مورد اپلت های Swing باید از Japplet ارث ببرند.

دیدگاه خود را به ما بگویید.