CodeGym /وبلاگ جاوا /Random-FA /اعلام روش
John Squirrels
مرحله
San Francisco

اعلام روش

در گروه منتشر شد
سلام! شما قبلاً درباره ایجاد کلاس های خود با فیلدها و متدها می دانستید. اکنون به روش ها می پردازیم.
اعلام روش - 1
البته ما قبلاً بیش از یک بار در درس هایمان این کار را انجام داده ایم، اما عمدتاً به کلیات پرداخته ایم. امروز، ما قصد داریم روش‌ها را تشریح کنیم، و روش‌های مختلف ایجاد آن‌ها، و نحوه مدیریت همه آن‌ها را مطالعه کنیم. :) بیا بریم!

اعلام روش

تمام کدهایی که یک متد را تعریف می کنند، اعلان متد نامیده می شوند . شکل کلی اعلان متد را می توان به صورت زیر توصیف کرد:
access modifier, return type, method name (parameter list) {
    // method body
}
به عنوان مثال، به اعلان‌های متدهای مختلف کلاس نگاهی بیندازید Dog.
public class Dog {

   String name;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {
       Dog max = new Dog("Max");
       max.woof();

   }

   public void woof() {
       System.out.println("A dog named " + name + " says \"Woof, woof!\"");
   }

   public void run(int distanceInFeet) {
       System.out.println("A dog named " + name + " ran " + distanceInFeet + " feet!");
   }

   public String getName() {
       return name;
   }
}

1. اصلاح کننده دسترسی

اصلاح کننده دسترسی همیشه ابتدا نشان داده می شود. تمام Dogمتدهای کلاس با اصلاح کننده عمومی مشخص شده اند . این بدان معنی است که ما می توانیم آنها را از هر کلاس دیگری فراخوانی کنیم:
public class Main {

   public static void main(String[] args) {

       Dog butch = new Dog("Butch");
       butch.run(100);
   }

}
همانطور که می بینید، Dogمتدهای کلاس به راحتی در Mainکلاس قابل دسترسی هستند. این به دلیل تغییر دهنده عمومی امکان پذیر است . در جاوا، اصلاح کننده های دیگری نیز وجود دارد. همه آنها اجازه نمی دهند که متدها در کلاس های دیگر استفاده شوند. در درس های دیگر در مورد آنها صحبت خواهیم کرد. نکته اصلی که باید به خاطر بسپارید این است که اصلاح کننده چه مسئولیتی دارد: آیا یک متد در کلاس های دیگر قابل دسترسی است :)

2. کلیدواژه ثابت

یکی از Dogروش ها، main()با کلمه کلیدی static مشخص شده است . همچنین بخشی از اعلان متد است و ما از قبل معنای آن را می دانیم. در قالب اعلان متد که در ابتدای درس داده شد به آن اشاره نکردیم، زیرا اختیاری است. اگر مشخص شده است، پس باید بعد از اصلاح کننده دسترسی بیاید. به یاد دارید که در درس های اخیر در مورد متغیرهای ثابت (کلاس) صحبت کردیم؟ هنگامی که برای متدها اعمال می شود، این کلمه کلیدی تقریباً همان معنی را دارد. اگر متد ایستا باشد ، می توان آن را بدون ارجاع به یک شی خاص از کلاس استفاده کرد. Dogو در واقع، برای اجرای main()متد استاتیک در کلاس ، به شی نیازی ندارید Dog. بدون یکی به خوبی اجرا خواهد شد. اگر این متد ثابت نبود، ابتدا باید یک شیء ایجاد کنیم تا بتوانیم آن را اجرا کنیم.

3. ارزش بازگشتی

اگر متد ما باید چیزی را برگرداند، نوع مقدار بازگشتی را مشخص می کنیم. این از مثال گیرنده مشهود است getName():
public String getName() {
   return name;
}
یک Stringشی را برمی گرداند. اگر روشی چیزی را برنمی گرداند، در عوض از کلمه کلیدی void استفاده می شود، مانند woof()روش:
public void woof() {
   System.out.println("A dog named " + name + " says \"Woof, woof!\"");
}

روش هایی با همین نام

شرایطی وجود دارد که ما چندین روش مختلف برای فراخوانی یک متد می خواهیم. چرا هوش مصنوعی خودمان را ایجاد نکنیم؟ آمازون الکسا دارد، اپل سیری دارد، پس چرا ما یکی نداشته باشیم؟ :) در فیلم مرد آهنی، تونی استارک هوش مصنوعی باورنکردنی خود، جارویس را خلق می کند. بیایید به آن شخصیت فوق العاده ادای احترام کنیم و هوش مصنوعی خود را به افتخار او نام گذاری کنیم. :) اولین کاری که باید انجام دهیم این است که به جارویس یاد بدهیم به افرادی که وارد اتاق می شوند سلام کند (عجیب خواهد بود اگر چنین عقل شگفت انگیزی بی ادب باشد).
public class Jarvis {

   public void sayHi(String name) {
       System.out.println("Good evening, " + name + ". How are you?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
   }
}
خروجی کنسول: عصر بخیر، تونی استارک. چطور هستید؟ خیلی خوب! جارویس اکنون می تواند از مهمانان پذیرایی کند. البته، بیشتر از استاد او، تونی استارک. اما اگر تنها نیاید چه می شود! اما sayHi()روش ما فقط یک آرگومان را می پذیرد. و بنابراین فقط می تواند به یک نفر که وارد اتاق می شود سلام کند و دیگری را نادیده بگیرد. خیلی مودب نیست، موافقی؟ :/ در این صورت می‌توانیم با نوشتن 2 متد با یک نام، اما پارامترهای مختلف، مشکل را حل کنیم:
public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Good evening, " + firstGuest + ". How are you?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
   }

}
به این روش اضافه بار می گویند . بارگذاری بیش از حد روش به برنامه ما امکان می دهد انعطاف پذیرتر باشد و روش های مختلف کار را در خود جای دهد. بیایید نحوه عملکرد آن را مرور کنیم:
public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Good evening, " + firstGuest + ". How are you?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
خروجی کنسول: عصر بخیر، تونی استارک. چطور هستید؟ عصر بخیر، تونی استارک و کاپیتان آمریکا. چطور هستید؟ عالی بود هر دو نسخه کار کردند :) اما ما مشکل را حل نکردیم! اگر سه مهمان باشد چه؟ البته می‌توانیم sayHi()روش را دوباره بارگذاری کنیم، به طوری که سه نام مهمان را بپذیرد. اما می تواند 4 یا 5 باشد. تمام راه تا بی نهایت. sayHi()آیا راه بهتری برای آموزش جارویس برای مدیریت هر تعداد نام، بدون بارگذاری بیش از حد متد یک میلیون بار () وجود ندارد ؟ :/ البته هست! اگر نبود، به نظر شما جاوا محبوب ترین زبان برنامه نویسی در جهان بود؟ ;)
public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Good evening, " + name + ". How are you?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
وقتی از ( String... names ) به عنوان پارامتر استفاده می شود، نشان می دهد که مجموعه ای از رشته ها به متد ارسال می شود. لازم نیست از قبل مشخص کنیم که چه تعداد خواهد بود، بنابراین اکنون روش ما بسیار انعطاف پذیرتر است:
public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Good evening, " + name + ". How are you?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
   }
}
خروجی کنسول: عصر بخیر، تونی استارک. چطور هستید؟ عصر بخیر کاپیتان آمریکا چطور هستید؟ عصر بخیر، بیوه سیاه. چطور هستید؟ عصر بخیر هالک چطور هستید؟ در داخل متد، همه آرگومان ها را تکرار می کنیم و عبارات فرمت شده با نام را نمایش می دهیم. در اینجا ما از یک for-eachحلقه ساده شده (که قبلاً دیده اید) استفاده می کنیم. اینجا عالی است، زیرا علامت گذاری ( String... names ) در واقع به این معنی است که کامپایلر تمام آرگومان های ارسال شده را در یک آرایه قرار می دهد. در نتیجه، ما می‌توانیم با نام متغیرها همانطور که با یک آرایه کار می‌کنیم، از جمله با تکرار آن در یک حلقه، کار کنیم. به علاوه، آن را با هر تعداد رشته های عبور کار می کند! دو، ده، حتی هزار - این روش با هر تعداد مهمان به درستی کار خواهد کرد. خیلی راحت تر از بارگذاری بیش از حد روش برای همه احتمالات، فکر نمی کنید؟ :) در اینجا مثال دیگری از بارگذاری بیش از حد روش است. بیایید یک printInfoFromDatabase()روش به جارویس بدهیم. اطلاعات یک شخص را از پایگاه داده نمایش می دهد. اگر پایگاه داده نشان دهد که شخصی یک ابرقهرمان یا ابرشرور است، ما آن اطلاعات را نشان خواهیم داد:
public class Jarvis {

   public void printInfoFromDatabase (String bio) {

       System.out.println(bio);
   }

   public void printInfoFromDatabase(String bio, boolean isEvil, String nickname) {

       System.out.println(bio);
       if (!isEvil) {
           System.out.println("Also known as the superhero " + nickname);
       } else {
           System.out.println("Also known as the supervillain " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Laura Palmer. Date of birth: July 22, 1972. Twin Peaks, Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Max Eisenhardt. Height: 15.6 ft. Weight: 189 lbs. ", true, "Magneto");
   }
}
خروجی: لورا پالمر تاریخ تولد: 22 جولای 1972. توئین پیکس، واشنگتن مکس آیزنهارت. قد: 15.6 فوت وزن: 189 پوند. همچنین به عنوان ابر شرور Magneto شناخته می شود بنابراین، رفتار روش ما بستگی به داده هایی دارد که به آن ارسال می کنیم. در اینجا یک نکته مهم دیگر وجود دارد: ترتیب استدلال ها مهم است! فرض کنید روش ما یک رشته و یک عدد می گیرد:
public class Person {

   public static void sayYourAge(String greeting, int age) {
       System.out.println(greeting + " " + age);
   }

   public static void main(String[] args) {

       sayYourAge("My age is ", 33);
       sayYourAge(33, "My age is "); // Error!
   }
}
اگر متد Personکلاس sayYourAge()یک رشته و یک عدد را به عنوان ورودی بگیرد، این ترتیبی است که این آرگومان ها باید به متد ارسال شوند! اگر آنها را به ترتیب دیگری ارسال کنیم، کامپایلر یک خطا ایجاد می کند و فرد نمی تواند سن خود را بگوید. ضمنا سازنده ها هم که در درس آخر بهشون پرداختیم روش هستن! شما همچنین می توانید آنها را بیش از حد بارگذاری کنید (یعنی چندین سازنده با مجموعه های مختلف پارامترها ایجاد کنید) و ترتیب آرگومان های ارسال شده برای آنها نیز اساساً مهم است. آنها روش های واقعی هستند! :)

نحوه فراخوانی متدهایی با پارامترهای مشابه

همانطور که می دانید nullیک کلمه کلیدی در جاوا است. درک این موضوع بسیار مهم است که nullنه یک شی و نه یک نوع داده است . تصور کنید که ما یک Personکلاس و یک introduce()متد داریم که نام و سن فرد را اعلام می کند. علاوه بر این، سن را می توان به صورت متن یا عدد عبور داد.
public class Person {

   public void introduce(String name, String age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person alex = new Person();
       alex.introduce ("Alex", "twenty-one");

       Person mary = new Person();
       mary.introduce("Mary", 32);
   }
}
ما قبلاً با بارگذاری بیش از حد آشنا هستیم، بنابراین می دانیم که هر دو روش همانطور که باید رفتار می کنند: نام من Alex است. سن من بیست و یک سال است نام من مریم است. سن من 32 سال استnull اما اگر به جای رشته یا عدد به عنوان پارامتر دوم ارسال کنیم چه اتفاقی می افتد ؟
public static void main(String[] args) {

   Person victor = new Person();
   victor.introduce("Victor", null);// Ambiguous method call!
}
با خطای کامپایل مواجه خواهیم شد! علت این امر چیست و «ابهام» دقیقاً چیست؟ در واقع، همه چیز بسیار ساده است. مشکل این است که ما دو نسخه از روش داریم: یکی با a Stringبه عنوان آرگومان دوم و دیگری با an Integerبه عنوان آرگومان دوم. اما a Stringو an Integerهر دو می توانند باشند null! از آنجا که آنها انواع مرجع هستند، nullمقدار پیش فرض برای هر دوی آنها است. به همین دلیل است که در این شرایط کامپایلر نمی تواند بفهمد که کدام نسخه از متد را باید فراخوانی کند. راه حل این مشکل بسیار ساده است. Nullرا می توان به صراحت به یک نوع مرجع خاص تبدیل کرد. بنابراین، هنگامی که یک متد را فراخوانی می کنید، می توانید نوع داده مورد نظر برای آرگومان دوم را در داخل پرانتز نشان دهید! کامپایلر "اشاره" شما را درک می کند و روش صحیح را فراخوانی می کند:
public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Method with a string and a number!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", (String) null);
   }
}
خروجی: روش با دو رشته! اسم من ویکتور است. سن من تهی است توجه داشته باشید که اگر پارامتر عدد intبه جای نمونه ای از نوع مرجع Integer یک نمونه اولیه بود، چنین خطایی وجود نداشت.
public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Method with a string and a number!!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", null);
   }
}
می توانید حدس بزنید چرا؟ اگر حدس زدید چرا، آفرین! :) چون بدوی ها نمی توانند null. اکنون کامپایلر تنها یک انتخاب دارد، یعنی introduce()متد را با دو رشته فراخوانی کند. این نسخه ای از متد است که با هر بار فراخوانی متد اجرا می شود.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION