CodeGym /בלוג Java /Random-HE /הצהרת שיטה
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. זה אפשרי בגלל השינוי הציבורי . ב-Java, ישנם מתקנים אחרים. לא כולם מאפשרים שימוש בשיטות במחלקות אחרות. נדבר עליהם בשיעורים אחרים. הדבר העיקרי שיש לזכור הוא על מה אחראי המשנה: האם מתודה נגישה במחלקות אחרות :)

2. מילת מפתח סטטית

אחת Dogהשיטות, main(), מסומנת במילת המפתח static . זה גם חלק מהצהרת השיטה, ואנחנו כבר יודעים את המשמעות שלה. לא הזכרנו את זה בתבנית הצהרת השיטה שניתנה בתחילת השיעור, כי זה אופציונלי. אם הוא צוין, הוא חייב לבוא אחרי משנה הגישה. זוכרים שבשיעורים האחרונים דיברנו על משתנים סטטיים (מעמדיים)? כאשר מיושמת על שיטות, למילת מפתח זו יש בערך אותה משמעות. אם מתודה היא סטטית , ניתן להשתמש בה ללא התייחסות לאובייקט ספציפי של המחלקה. ואכן, לא צריך אובייקט Dogכדי להפעיל את main()המתודה הסטטית במחלקה Dog. זה יפעל בסדר גמור בלי אחד. אם שיטה זו לא הייתה סטטית, היינו צריכים קודם כל ליצור אובייקט כדי להפעיל אותו.

3. החזר ערך

אם השיטה שלנו צריכה להחזיר משהו, אז אנו מציינים את סוג ערך ההחזרה. זה בולט מהדוגמה של ה- getName()getter:
public String getName() {
   return name;
}
זה מחזיר אובייקט String. אם שיטה לא מחזירה כלום, במקום זאת נעשה שימוש במילת מפתח ריק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()השיטה מיליון פעמים()? :/ ברור שיש! אם לא היה, האם אתה חושב ש-Java תהיה שפת התכנות הפופולרית ביותר בעולם? ;)
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 ) משמש כפרמטר, זה מציין שאוסף של Strings יועבר לשיטה. אנחנו לא צריכים לציין מראש כמה יהיו, אז עכשיו השיטה שלנו הרבה יותר גמישה:
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);
   }
}
אנחנו כבר מכירים את עומס יתר, אז אנחנו יודעים ששתי השיטות יתנהגו כמו שצריך: שמי אלכס. הגיל שלי הוא עשרים ואחת שמי מרי. הגיל שלי הוא 32 אבל מה יקרה אם נעבור nullכפרמטר שני במקום מחרוזת או מספר?
public static void main(String[] args) {

   Person victor = new Person();
   victor.introduce("Victor", null);// Ambiguous method call!
}
נקבל שגיאת קומפילציה! מה גורם לכך ומהי בעצם ה"עמימות"? למעשה, הכל מאוד פשוט. הבעיה היא שיש לנו שתי גרסאות של השיטה: אחת עם a Stringבתור הארגומנט השני, ואחת עם an Integerבתור הארגומנט השני. אבל א 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);
   }
}
פלט: שיטה עם שני מיתרים! שמי הוא ויקטור. הגיל שלי הוא null שים לב שאילו פרמטר המספר היה פרימיטיבי int, ולא מופע מסוג הפניה של מספר שלם, לא הייתה שגיאה כזו.
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