تعریف متد
یک متد شامل اسم، نوعی که بر میگردونه، پارامتر و بدنه است.
به مجموعه ی دستورات داخل یک بدنه ی دارای نام که برای انجام یک عملیات، هنگام صدا زدن نام بدنه اجرا میشن، متد میگیم.
اسم دیگه ی متد، تابع است؛ اما در جاوا به متد معروف است.
به طور کلی متد (تابع) یه سری کد ها رو به عنوان پارامتر از ورودی میگیره و نتیجه رو به عنوان خروجی بر میگردونه. متد ها کد های برنامه رو خواناتر قابل درک تر و سادهتر میکنن و از دوباره نویسی کد های تکراری جلوگیری میکنن.
ساختار متد
فرم کلی:
تصویر زیر نمایانگر فرم کلی ساختار یک متد در جاواست.
1- کلیدواژه ی سطح دسترسی
بیان کننده ی سطح دسترسی به متد در پروژه است؛ سطح دسترسی میتونه public, private, protected یا default باشه.
2- کلیدواژه ی استاتیک
اگه هنگام تعریف متد از کلیدواژه ی استاتیک استفاده کنیم میگیم یک متد استاتیک تعریف کرده ایم. تعریف متد ملزم به استفاده از کلیدواژه ی استاتیک نیست.
معروف ترین متد استاتیک، متد main است که محل اجرای کد های برنامه های استاندارد جاوا است.
3- نوعی که توسط متد برگردونده میشه
نوع R میتونه Primitive, Object یا void (تهی) باشه. اگه R از نوع void باشه، به این معنیه که هیچ مقداری توسط متد برگردونده نمیشه و فقط کد های داخل متد اجرا میشن.
4- نام متد
نام دلخواهیه که برای متد درنظر میگیریم.
5- پارامتر های متد
با تعریف پارامتر برای متد، میتونیم مقادیری رو هنگام صدا زدن متد داخلش پاس بدیم. بعد از تعریف هر پارامتر با یک ویرگول میتونیم پارامتر بعدی رو برای متد تعریف کنیم؛ در تصویر t0، t1 ... tn پارامتر های متد هستند، میتونیم یک یا چند پارامتر برای متد تعریف کنیم.
6- مقداری که متد بر میگردونه
با کلیدواژه ی return میتونیم مقداری از جنس R رو برگردونیم.
توجه
متد باید مقداری از نوع R برگردونه و اگه مقدار از نوع R نباشه دچار خطای کامپایل میشیم. R میتونه Primitive یا Object باشه.
توجه
میتونیم از return هرجای متد که خواستیم استفاده کنیم، در اینصورت بعد از اجرای return کد های بعد از return اجرا نمیشه.
صدا زدن متد
دو حالت میتونیم متد رو صدا کنیم.
صدا زدن متد داخل کلاسی که متد تعریف شده
اگه متد رو بخوایم داخل کلاسی که تعریفش کردیم صدا کنیم کافیه اسم متد رو مانند زیر نوشته و پارامتر های لازم رو بهش پاس بدیم.
Type0 t0 = ...;
Type1 t1 = ...;
...
TypeN tn = ...;
R returnedValue = myMethod(t0, t1, ..., tn);
صدا زدن متد در خارج از کلاسی که متد تعریف شده
اگه متد رو بخوایم در خارج از کلاس صدا بزنیم باید اسم متغیر آبجکت رو نوشته، نقطه بزاریم و متد مورد نظر داخل کلاس رو صدا کنیم.
Type0 t0 = ...;
Type1 t1 = ...;
...
TypeN tn = ...;
MyObject obj = new MyObject(...);
//صدا زدن متد و پاس دادن پارامتر ها
R returnedValue = obj.myMethod(t0, t1, ..., tn);
راهنمایی
میتونیم متد های استاتیک رو در خارج از کلاس با نوشتن اسم کلاس و نقطه صدا بزنیم؛ این کار به لحاظ تفکیک متد های آبجکتی از استاتیک در ظاهر کد ها توصیه میشه.
Type0 t0 = ...;
Type1 t1 = ...;
...
TypeN Tn = ...;
//صدا زدن متد و پاس دادن پارامتر ها
R returnedValue = MyClass.myStaticMethod(t0, t1, ..., tn);
مثال:
میخوایم یک متد تعریف کنیم تا maximum بین دو عدد رو برگردونه.
public static void main(String[] args) {
int i = 5;
int j = 2;
int k = max(i, j);
System.out.println("The maximum of " + i +
" and " + j + " is " + k);
}
public static int max(int num1, int num2) {
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
میتونیم از return داخل شرط هم استفاده کنیم در این صورت با اجرا شدن return مقدار برگردونده میشه و از اجرای بقیه ی کد در داخل متد جلوگیری میشه.
مثال
در زیر یک متد استاتیک با سطح دسترسی public تعریف کردیم؛ داخل متد بررسی میکنه اگه عدد زوج باشه مربع اون عدد رو برگردونه در غیر اینصورت 1- رو بر میگردونه.
public static void main(String[] args){
int square1 = squareEven(14);
int square2 = squareEven(43);
System.out.println("is 14 even? " + (square1 != -1) + " the square of 14 is " + square1);
System.out.println("is 43 even? " + (square2 != -1) + " the square of 43 is " + square2);
}
public static int squareEven(int number){
if(number % 2 != 0) return -1;
return number * number;
}
اگه از return داخل دستور شرطی استفاده کنیم که else داشته باشه return در else به عنوان آخرین قسمت کد در متد توسط کامپایلر شناخته میشه و دیگه نیاز نیست return در پایین متد بنویسیم.
public R myMethod(...){
...
if(condition0){
...
return r0;
}else if(condition1){
...
return r1;
}else if(condition2){
...
return r2;
}else {
...
return r3;
}
}
public static int max(int num1, int num2){
if(num1 > num2) {
return num1;
}
else{
return num2;
}
}
متد تهی (void)
به متدی که هیچ مقداری رو بر نگردونه متد void میگیم.
کلمه ی void یعنی پوچ و تهی؛ چون این متد ها مقداری رو بر نمیگردونن برای همین بهشون متد void میگیم.
برای تعریف متد void، بهجای نوشتن نوعی که میخوایم برگردونیم از کلیدواژه ی void در جاوا استفاده میکنیم.
مثال
public static void main(String[] args){
printMessage("You can call me anytime u wish");
}
private static void printMessage(String message){
System.out.println("Message: " + message);
}
در متد void میتونیم از کلیدواژه ی return برای جلوگیری از اجرای بقیه ی کد های داخل متد استفاده کنیم.
مثال
public static void main(String[] args){
printSquareEven(13);
printSquareEven(24);
}
private static void printSquareEven(int n){
if(n % 2 != 0) {
System.out.println("Not square even");
return;
}
int square = n * n;
System.out.println("Square of " + n + " is " + square);
}
پارامتر های متد
میتونیم مقادیر یا متغیر های primary و آبجکتی رو به عنوان پارامتر داخل متد پاس بدیم.
پارامتر های متد متغیر هستند، مقدار متغیری که به عنوان پارامتر به متد پاس داده میشه در واقع یک کپی از مقدار اصلی متغیر است که توسط JVM کپی میشه.
پاس دادن متغیر های primary به عنوان پارامتر
در مثال زیر یک متد به نام increment تعریف میکنیم و سپس مقدار x رو قبل از متد، داخل متد و بعد از متد نمایش میدیم.
public static void main(String[] args) {
int x = 1;
System.out.println("Before the call, x is " + x);
increment(x);
System.out.println("After the call, x is " + x);
}
public static void increment(int c) {
c++;
System.out.println("Inside the method x is " + c);
}
پاس دادن متغیر های آبجکتی به عنوان پارامتر
متغیر های آبجکتی به خودی خود نگهدارنده ی مقادیر نیستند و فقط اشاره به آبجکت ساخته شده در حافظه میکنن؛ وقتی یک متغیر آبجکتی رو به عنوان پارامتر داخل متد پاس میدیم، JVM یک کپی از ادرس آبجکت رو به عنوان مقدار پارامتر قرار میده و از اونجایی که هردو آدرس به یک آبجکت مشترک در حافظه اشاره میکنن پس تغییراتی که روی آبجکت در داخل متد اتفاق میوفته با خارج از متد یکیه.
مثال
ابتدا میخوایم بدون اختصاص آبجکت جدید به innerText در داخل متد، "Test" رو به innerText اضافه کنیم.
public static void main(String[] args){
StringBuilder outerText = new StringBuilder("Hello ");
System.out.println("before calling method: " + outerText);
test(outerText);
System.out.println("after calling method: " + outerText);
}
private static void test(StringBuilder innerText){
innerText.append("Test");
System.out.println("on calling method: " + innerText);
}
در بالا با افزودن مقدار Test به innerText متن outerText هم تغییر میکنه چون هردو به یک آبجکت در حافظه دارن اشاره میکنن.
حالا اگه innerText در داخل متد به یک آبجکت جدید در حافظه اشاره کنه، با تغییرات در آبجکت توسط innerText، محتوای آبجکت در outerText تغییری نمیکنه.
public static void main(String[] args){
StringBuilder outerText = new StringBuilder("Hello ");
System.out.println("before calling method: " + outerText);
test(outerText);
System.out.println("after calling method: " + outerText);
}
private static void test(StringBuilder innerText){
innerText = new StringBuilder("Test");
System.out.println("on calling method: " + innerText);
}
مفهوم overloading
در یک کلاس میتونیم یک متد رو با همون اسم با پارامتر های مختلف تعریف کنیم که بهش overloading در جاوا میگیم.
public static void main(String[] args){
System.out.println("The maximum of 3 and 4 is " + max(3, 4));
System.out.println("The maximum of 3.0 and 5.4 is " + max(3.0, 5.4));
System.out.println("The maximum of 3.0, 5.4, and 10.14 is " + max(3.0, 5.4, 10.14));
}
private static int max(int n1, int n2){
return n1 > n2 ? n1 : n2;
}
private static double max(double n1, double n2){
return n1 > n2 ? n1 : n2;
}
private static double max(double n1, double n2, double n3){
return max(max(n1, n2), n3);
}
در مثال بالا شاید عجیب به نظر بیاد، هنگامی که متد های max رو تعریف و صدا زدیم از کجا بدونیم کدوم متد صدا زده میشه؟ جواب این سؤال با کامپایلر است؛ هنگامی که مقداریو به عنوان پارامتر به متد پاس میدیم کامپایلر به طور خودکار مناسب ترین متد رو انتخاب میکنه.
مورد مطالعه (مثال ها)
در مثال زیر متد getGrade با دریافت امتیاز رتبه ی افراد رو برمیگردونه.
public static void main(String[] args) {
System.out.print("The grade is " + getGrade(78.5));
System.out.print("\nThe grade is " + getGrade(59.5));
}
public static char getGrade(double score) {
if (score >= 90.0)
return 'A';
else if (score >= 80.0)
return 'B';
else if (score >= 70.0)
return 'C';
else if (score >= 60.0)
return 'D';
else
return 'F';
}
در مثال زیر متد gcd بزرگترین مخرج مشترک (ب.م.م) بین دو عدد رو بر میگردونه.
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter first number: ");
int number0 = input.nextInt();
System.out.println("Enter second number: ");
int number1 = input.nextInt();
System.out.println("the greatest common divisor for " + number0 + " and " + number1 + " is " + gcd(number0, number1));
}
private static int gcd(int n0, int n1){
int gcd = 1;
for (int i= 2 ; i <= n0 && i<= n1; i++ ){
if (n0 % i == 0 && n1 % i== 0)
gcd = i;
}
return gcd;
}
در مثال زیر میخوایم صد تا عدد اول رو پیدا کنیم:
public static void main(String[] args) {
System.out.println("The first 100 Prime numbers are: ");
printPrimeNumbers(100);
}
public static void printPrimeNumbers(int numberOfPrimes){
final int NUMBER_OF_PRIMES_PER_LINE = 10;
int count = 0;
int number = 2;
while (count < numberOfPrimes){
//بررسی میکنه عدد اول است یا خیر
if (isPrime(number)){
count++;
if (count % NUMBER_OF_PRIMES_PER_LINE == 0) System.out.printf("%-5d\n", number);
else System.out.printf("%-5d", number);
}
//با هر بار تکرار میریم سراغ عدد بعدی و تا زمانی که count کوچیکتر از numberOfPrimes باشه حلقه تکرار میشه
number++;
}
}
private static boolean isPrime(int number){
for (int divisor = 2; divisor <= number/2; divisor++){
if (number % divisor == 0) return false;
}
return true;
}
در مثال زیر برنامه یک عدد hexadecimal رو از ورودی میگیره و مقدار decimal عدد رو بر میگردونه.
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a hex number: ");
String hex = input.next();
System.out.println("Decimal number of " + hex + " is " + hexToDecimal(hex));
}
public static int hexToDecimal(String hex){
hex = hex.toUpperCase();
int decimal = 0;
for (int i=0; i < hex.length(); i++){
char hexChar = hex.charAt(i);
decimal = decimal * 16 + hexCharToDecimal(hexChar);
}
return decimal;
}
private static int hexCharToDecimal(char ch){
if (ch >= 'A' && ch <= 'F') return 10 + ch - 'A';
else return ch - '0';
}
خلاصه
- یک متد شامل نام، نوعی که برمیگردونه، پارامتر و بدنه است.
- از متد برای مرتب شدن کد ها، جلوگیری از دوباره نویسی و قابل درک تر کردن کد های برنامه استفاده میکنیم.
- پارامتر های متد، متغیر های جدید هستند و مقدار متغیری که در بیرون از متد، به متد پاس میدیم، توسط JVM براشون کپی میشه.
- به متدی که هیچ مقداری رو بر نمیگردونه متد void در جاوا میگیم.
- وقتی چند متد با یک نام و پارامتر های متفاوت داشته باشیم بهش overloading میگیم.