فصل 16: اورلود (Overload) و اورراید (Override) متدها در جاوا

24 مرداد 1397
overload-override-java

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

برای مثال در نظر بگیرید که عملیات جمع را می خواهید روی چند عدد انجام دهید. می توانید یک متد با دو پارامتر برای جمع کردن دو پارامتر، یک متد با سه پارامتر برای جمع کردن سه پارامتر و... داشته باشید. از آنجایی که تمام این متدها یک کار را انجام میدهند، توصیه می شود که تمام متدها اسم یکسانی داشته باشند (مثلا add).

مزیت استفاده از متد اورلود این است که خوانایی کد را بالا می برد.

راه های اورلود (Overload) متد در جاوا

  1. تغییر تعداد آرگومان‌های ورودی
  2. تغییر نوع داده آرگومان های ورودی

توجه داشته باشید که در صورت تغییر دادن نوع داده بازگشتی، اورلود اتفاق نمی افتد.

1- تغییر دادن تعداد آرگومان های ورودی

در این مثال همان متد جمع اعداد را پیاده سازی کردیم  و ضمنا از متدهای استاتیک استفاده کردیم تا مجبور به ساخت شی نشویم.

مثال:

class Adder{  
static int add(int a,int b){return a+b;}  
static int add(int a,int b,int c){return a+b+c;}  
}  
class TestOverloading1{  
public static void main(String[] args){  
System.out.println(Adder.add(11,11));  
System.out.println(Adder.add(11,11,11));  
}}

خروجی:

22
33

2- تغییر دادن نوع داده آرگومان های ورودی

متد اول داده هایی از نوع عدد صحیح و دیگری متدهایی از نوع عدد اعشاری یا double دارد.

مثال:

class Adder{  
static int add(int a, int b){return a+b;}  
static double add(double a, double b){return a+b;}  
}  
class TestOverloading2{  
public static void main(String[] args){  
System.out.println(Adder.add(11,11));  
System.out.println(Adder.add(12.3,12.6));  
}}

خروجی:

22
24.9

سوال: چرا با تغییر نوع داده بازگشتی متد اورلود اتفاق نمی افتد؟

به خاطر پیچیدگی برنامه و ایجاد ابهام، در جاوا امکان متد اورلود با تغییر نوع داده بازگشتی وجود ندارد. به مثال زیر توجه کنید:

مثال:

class Adder{  
static int add(int a,int b){return a+b;}  
static double add(int a,int b){return a+b;}  
}  
class TestOverloading3{  
public static void main(String[] args){  
System.out.println(Adder.add(11,11));//ambiguity  
}}

خروجی:

Compile Time Error: method add(int,int) is already defined in class Adder

اورلود main()

امکان اورلود کردن main() نیز با استفاده از تکنیک هایی که گفته شد وجود دارد اما JVM تنها متد main() که آرگومان ورودی آن آرایه‌ای از رشته‌ها باشد را اجرا می کند.

مثال:

class TestOverloading4{  
public static void main(String[] args){System.out.println("main with String[]");}  
public static void main(String args){System.out.println("main with String");}  
public static void main(){System.out.println("main without args");}  
}  

خروجی:

main with String[]

معرفی مفهوم Overload در جاوا

ارتقا نوع داده در متد اورلود (Overload)

در صورتی که آرگومان ورودی ما دقیقا با نوع آرگومانی که در متد مشخص شده است، یکسان نباشد، آنگاه در بعضی اوقات ارتقا نوع داده یا Type Promotion اتفاق می افتد. به این معنا که از int می توان به جای float، double و long استفاده کرد یا از short می توان به جای int، float و... استفاده کرد. در شکل بالا به صورت کامل مشخص شده است این موارد. برای یادگیری این مفهوم مثال زیر را با دقت ببینید:

مثال:

class OverloadingCalculation1{  
  void sum(int a,long b){System.out.println(a+b);}  
  void sum(int a,int b,int c){System.out.println(a+b+c);}  
  
  public static void main(String args[]){  
  OverloadingCalculation1 obj=new OverloadingCalculation1();  
  obj.sum(20,20);//now second int literal will be promoted to long  
  obj.sum(20,20,20);  
  
  }  
}

خروجی:

Output:40
       60

به مثال زیر نیز توجه کنید. در این مثال با اینکه از int می توان به جای long استفاده کرد اما به دلیل وجود متد با آرگومان های int، همان متد اجرا می شود.

مثال:

class OverloadingCalculation2{  
  void sum(int a,int b){System.out.println("int arg method invoked");}  
  void sum(long a,long b){System.out.println("long arg method invoked");}  
  
  public static void main(String args[]){  
  OverloadingCalculation2 obj=new OverloadingCalculation2();  
  obj.sum(20,20);//now int arg sum() method gets invoked  
  }  
}

خروجی:

Output:int arg method invoked

مثال زیر هم یک مثال نادر است که کامپایلر متوجه نمیشود که کدام متد را باید اجرا کند و در نتیجه ارور می دهد.

مثال:

class OverloadingCalculation3{  
  void sum(int a,long b){System.out.println("a method invoked");}  
  void sum(long a,int b){System.out.println("b method invoked");}  
  
  public static void main(String args[]){  
  OverloadingCalculation3 obj=new OverloadingCalculation3();  
  obj.sum(20,20);//now ambiguity  
  }  
}

خروجی:

Output:Compile Time Error

اورراید (Override) متد در جاوا

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

دلیل اورراید کردن متدها، اختصاصی کردن عملکرد یک متد در کلاس فرزند و دستیابی به چندریختی یا پلی مورفیسم است.

قوانین اورراید (Override) متد در جاوا

  1. نام متد در دو کلاس فرزند و پدر یکسان باشد
  2. پارامترهای یکسانی هر دو متد داشته باشند.
  3. رابطه پدرفرزندی یا IS-A برقرار باشد.

حال بگذارید ببینیم اگر امکان اورراید نباشد چه اتفاقی می افتد:

مثال:

class Vehicle{  
  void run(){System.out.println("Vehicle is running");}  
}  
class Bike extends Vehicle{  
    
  public static void main(String args[]){  
  Bike obj = new Bike();  
  obj.run();  
  }  
}

خروجی:

Output:Vehicle is running

حال مثال بالا را به کمک روش اورراید پیاده سازی می کنیم. توجه کنید:

مثال:

class Vehicle{  
void run(){System.out.println("Vehicle is running");}  
}  
class Bike2 extends Vehicle{  
void run(){System.out.println("Bike is running safely");}  
  
public static void main(String args[]){  
Bike2 obj = new Bike2();  
obj.run();  
}

خروجی:

Output:Bike is running safely

انواع روابط در جاوا

در ادامه یک مثال کاربردی تر میبینیم که یک کلاس پدر به نام Bank وجود دارد که بانک های مختلف از آن ارث بری کرده و هرکدوم نرخ بهره خاصی رو اعمال کردند.

مثال:

class Bank{  
int getRateOfInterest(){return 0;}  
}  
  
class SBI extends Bank{  
int getRateOfInterest(){return 8;}  
}  
  
class ICICI extends Bank{  
int getRateOfInterest(){return 7;}  
}  
class AXIS extends Bank{  
int getRateOfInterest(){return 9;}  
}  
  
class Test2{  
public static void main(String args[]){  
SBI s=new SBI();  
ICICI i=new ICICI();  
AXIS a=new AXIS();  
System.out.println("SBI Rate of Interest: "+s.getRateOfInterest());  
System.out.println("ICICI Rate of Interest: "+i.getRateOfInterest());  
System.out.println("AXIS Rate of Interest: "+a.getRateOfInterest());  
}  
}

خروجی:

Output:
SBI Rate of Interest: 8
ICICI Rate of Interest: 7
AXIS Rate of Interest: 9

سوال: آیا امکان اورراید کردن متدهای استاتیک وجود دارد؟

خیر؛ امکان اورراید کردن متدهای استاتیک وجود ندارد. علتش هم این است که متدهای استاتیک مربوط به نمونه خاصی نیستند بلکه مربوط به خود کلاس است پس امکان اورراید آن وجود ندارد. در ضمن توجه کنید که نمونه های ما در بخش heap قرار دارند.

سوال: آیا امکان اورراید main() وجود دارد؟

خیر زیرا یک متد استاتیک است.

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.