מחלקות גנריות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 54 מתוך 87.
עכשיו, אחרי שהבנת למה גנריות שימושיות, בוא ניצור מחלקה גנרית משלך. מחלקה גנרית מצהירה על פרמטרי טיפוס אחד או יותר בתוך סוגריים זוויתיים אחרי שם המחלקה, שאפשר להשתמש בהם בכל רחבי המחלקה.
class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}T הוא פרמטר טיפוס: מציין מקום שמוחלף בטיפוס ממשי כשיוצרים מופע. אפשר להשתמש בכל שם, אבל מקובל להשתמש באותיות גדולות בודדות: T עבור Type, E עבור Element, K עבור Key, V עבור Value.
בעת יצירת מופע של מחלקה גנרית, מציינים את הטיפוס בפועל בתוך סוגריים זוויתיים:
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // אין צורך בהמרת טיפוס
Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();שימו לב לאופרטור <> (אופרטור היהלום) בצד ימין: Java מסיקה את הטיפוס מתוך ההצהרה. אפשר גם להשתמש בכמה פרמטרים של טיפוס עבור מחלקות שצריכות לעבוד עם יותר מטיפוס אחד:
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> pair = new Pair<>("age", 25);אתגר
קלבואו נבנה מערכת לניהול מתנות שמדגימה את העוצמה של מחלקות גנריות. תיצרו מערכת אחסון גמישה שיכולה להכיל כל סוג של פריט מתנה, וכן רישום שמקשר בין שמות המתנות לפרטים שלהן באמצעות כמה פרמטרים של טיפוסים.
תארגנו את הקוד שלכם בשלושה קבצים:
GiftBox.java: צרו מחלקה גנרית שיכולה לעטוף כל סוג של מתנה. למחלקהGiftBox<T>צריכים להיות שדה פרטיitemמטיפוסTושדה פרטיwrapped(בוליאני) שמתחיל בערךfalse. כללו בנאי שמקבל את הפריט, מתודהgetItem()שמחזירה את הפריט, מתודהwrap()שמגדירה את wrapped לערך true, ומתודהisWrapped()שמחזירה את מצב העטיפה. הוסיפו מתודהgetStatus()שמחזירה[item] (wrapped)או[item] (unwrapped), בהתאם למצב העטיפה.Registry.java: צרו מחלקה גנרית עם שני פרמטרים של טיפוסים, שמקשרת בין מקבל המתנה למתנה שלו. למחלקהRegistry<K, V>צריכים להיות שדות פרטייםrecipientמטיפוסKו-giftמטיפוסV. כללו בנאי שמקבל את שני הערכים, מתודות אחזורgetRecipient()ו-getGift(), ומתודהgetEntry()שמחזירה:[recipient] -> [gift]Main.java: הפיחו חיים ברישום המתנות שלכם! תקבלו שלוש קלטים: שם של מקבל מתנה (String), תיאור של המתנה (String) ושווי המתנה (מספר שלם המייצג דולרים).תחילה, צרו
GiftBox<String>שמכיל את תיאור המתנה. עטפו אותו באמצעות המתודהwrap(), ולאחר מכן הדפיסו את הסטטוס שלו.לאחר מכן, צרו
GiftBox<Integer>שמכיל את שווי המתנה (המייצג סכום של כרטיס מתנה). אל תעטפו אותו: הדפיסו את הסטטוס שלו כדי להציג שהוא אינו עטוף.לבסוף, צרו
Registry<String, String>שמקשר בין שם מקבל המתנה לתיאור המתנה, והדפיסו את רשומת הרישום.
תקבלו שלוש קלטים לפי הסדר: שם מקבל המתנה, תיאור המתנה ושווי המתנה (כמספר שלם).
שימו לב כיצד אותה מחלקה GiftBox פועלת בצורה חלקה גם עם טיפוסים String וגם עם טיפוסים Integer: זה היופי שבגנריקה! ומחלקת Registry מדגימה כיצד פרמטרים מרובים של טיפוסים מאפשרים ליצור צימודים גמישים בין כל שני טיפוסים.
נסו בעצמכם
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// קרא את הקלטים
String recipientName = scanner.nextLine();
String giftDescription = scanner.nextLine();
int giftValue = scanner.nextInt();
// TODO: צור GiftBox<String> המכילה את תיאור המתנה
// TODO: עטוף אותה באמצעות המתודה wrap()
// TODO: הדפס את המצב שלה באמצעות getStatus()
// TODO: צור GiftBox<Integer> המכילה את ערך המתנה
// TODO: אל תעטוף את זו - הדפס את המצב שלה (אמור להופיע כלא עטוף)
// TODO: צור Registry<String, String> המשייכת את הנמען לתיאור המתנה
// TODO: הדפס את הרשומה באמצעות getEntry()
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
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 אונליין