שיטות גנריות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 55 מתוך 87.
בעוד שמחלקות גנריות מאפשרות למחלקות שלמות לעבוד עם טיפוסים שונים, לפעמים צריך שרק שיטה אחת תהיה גנרית. שיטה גנרית מצהירה על פרמטר טיפוס משלה, ללא תלות בגנריות ברמת המחלקה.
פרמטר הטיפוס מופיע לפני טיפוס ההחזרה בחתימת המתודה:
public class Utility {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}
String[] names = {"Alice", "Bob"};
Integer[] numbers = {1, 2, 3};
Utility.printArray(names); // עובד עם String[]
Utility.printArray(numbers); // עובד עם Integer[]שימו לב ל־<T> שמופיע בין המשתנים המשנים לסוג ההחזרה. כך מצהירים על T כפרמטר טיפוס עבור המתודה הספציפית הזו. המהדר מסיק את הטיפוס בפועל מהארגומנטים שמעבירים.
מתודות גנריות יכולות גם להחזיר את הטיפוס הגנרי:
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}
String first = getFirst(new String[]{"a", "b"}); // מחזיר "a"אפשר להשתמש בכמה פרמטרי טיפוס כשצריך:
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String ו-Integer
printPair(1, "First"); // Integer ו-Stringמתודות גנריות שימושיות במיוחד במחלקות עזר, שבהן דרושות לך פעולות גמישות ושימושיות חוזרות בלי ליצור מחלקה גנרית.
אתגר
קלבואו נבנה ערכת כלים של פונקציות שירות שמדגימה את הגמישות של שיטות גנריות. תיצרו מחלקה עם שיטות לשימוש חוזר שעובדות עם כל סוג, ותראו כיצד שיטות גנריות יכולות להתקיים באופן עצמאי ממחלקות גנריות.
תארגנו את הקוד בשני קבצים:
ArrayUtils.java: צרו מחלקת שירות שמכילה שיטות גנריות לעבודה עם מערכים. במחלקה צריכות להיות שלוש שיטות גנריות סטטיות:getLast- שיטה גנרית שמקבלת מערך מסוגTומחזירה את האיבר האחרון. אם המערך ריק, החזירוnull.swap- שיטה גנרית שמקבלת מערך מסוגTושני אינדקסים של מספרים שלמים, ואז מחליפה בין האיברים שנמצאים במיקומים האלה. השיטה הזאת לא מחזירה דבר.printWithLabel- שיטה גנרית עם שני פרמטרים של סוג,Kו-V. היא מקבלת תווית מסוגKוערך מסוגV, ואז מדפיסה אותם בתבנית:[label]: [value]Main.java: הפעילו את השיטות הגנריות שלכם! תקבלו ארבעה קלטים: שתי מילים (מחרוזות) ושני מספרים (מספרים שלמים).תחילה, צרו מערך
String[]שמכיל את שתי המילים. השתמשו ב-getLastכדי לקבל את האיבר האחרון והדפיסו:Last word: [result]לאחר מכן, צרו מערך
Integer[]שמכיל את שני המספרים. קראו ל-swapכדי להחליף בין האיברים באינדקסים 0 ו-1, ואז הדפיסו:After swap: [first], [second]לבסוף, הדגימו את השיטה הגנרית עם שני הפרמטרים באמצעות קריאה ל-
printWithLabelפעמיים:- פעם אחת כשהמילה הראשונה היא התווית והמספר הראשון הוא הערך
- פעם אחת כשהמספר הראשון הוא התווית והמילה השנייה היא הערך
תקבלו ארבעה קלטים לפי הסדר: המילה הראשונה, המילה השנייה, המספר הראשון, המספר השני.
שימו לב שכל שיטה מצהירה על פרמטרי הסוג שלה באמצעות <T> או <K, V> לפני סוג ההחזרה. המהדר מסיק את הסוגים בפועל מתוך הארגומנטים שאתם מעבירים: אין צורך לציין אותם במפורש כשקוראים לשיטות!
נסו בעצמכם
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// קראו את נתוני הקלט
String firstWord = scanner.nextLine();
String secondWord = scanner.nextLine();
int firstNumber = scanner.nextInt();
int secondNumber = scanner.nextInt();
// TODO: צרו מערך String[] המכיל את שתי המילים
// TODO: השתמשו ב-ArrayUtils.getLast כדי לקבל את האיבר האחרון
// הדפיסו: "Last word: [result]"
// TODO: צרו מערך Integer[] המכיל את שני המספרים
// TODO: קראו ל-ArrayUtils.swap כדי להחליף בין האיברים באינדקסים 0 ו-1
// הדפיסו: "After swap: [first], [second]"
// TODO: קראו ל-ArrayUtils.printWithLabel עם firstWord כתווית ו-firstNumber כערך
// TODO: קראו ל-ArrayUtils.printWithLabel עם firstNumber כתווית ו-secondWord כערך
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותשדות (מאפיינים)מתודת הבנאיהעמסת בנאיםחזרה – מחשבון פשוט4ירושה
ירושה בסיסית (extends)מילת המפתח superדריסת מתודות (@Override)שרשור בנאיםהמחלקה Objectירושה יחידה ורב־רמתיתלמה אין ירושה מרובה של מחלקותסיכום – היררכיית עובדים7מתודות מיוחדות ומחלקת Object
מתודת toString()equals() ו-hashCode()מתודת clone()compareTo() ו-Comparableהממשק Comparatorסיכום – מיון מותאם אישית2מצייני גישה ואנקפסולציה
סקירה של רמות הגישהמתודות Getter ו-Setterהסתרת מידעמילת המפתח finalסיכום – מנהל חשבון בנק5פולימורפיזם
יסודות העמסת מתודותדריסת מתודות (בזמן ריצה)המרה כלפי מעלה וכלפי מטההאופרטור instanceofמחלקות ומתודות מופשטותסיכום – מחשבון צורות8מושגי OOP מתקדמים
הרכבה מול ירושהאגרגציה מול הרכבהמחלקות פנימיות, מקוננות ואנונימיותEnums ומתודות של EnumRecords (Java 16+)מחלקות חתומות (Java 17+)3מאפייני מחלקה וחברים סטטיים
משתני מופע לעומת משתנים סטטייםמתודות סטטיותבלוקים סטטייםקבועים (static final)סיכום — מונה ומחלקת עזר6ממשקים ומחלקות מופשטות
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםמתודות ברירת מחדל וסטטיות בממשקמחלקות מופשטות לעומת ממשקיםממשקים פונקציונלייםסיכום – מערכת תשלומיםתרגלו בעצמכם: קומפיילר Java אונליין