Menu
Coddy logo textTech

המרה כלפי מעלה וכלפי מטה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 30 מתוך 87.

בשיעור הקודם ראית כיצד משתנה מסוג האב יכול להכיל אובייקט צאצא: Animal myPet = new Dog(). השמה זו נקראת המרה כלפי מעלה (upcasting), והיא מתבצעת אוטומטית כי Dog הוא תמיד Animal.

המרה כלפי מעלה מתקדמת כלפי מעלה בהיררכיית הירושה. היא מתבצעת באופן משתמע ותמיד בטוחה:

Dog dog = new Dog();
Animal animal = dog;  // המרה לטיפוס אב - אוטומטית

בעת המרה למחלקת האב, אפשר לגשת רק למתודות שהוגדרו במחלקת האב. המתודות הייחודיות למחלקת הבת נעשות מוסתרות, אף על פי שמתחת לפני השטח האובייקט עדיין מסוג Dog.

המרה כלפי מטה פועלת בכיוון ההפוך, וממירה הפניה למחלקת אב בחזרה לטיפוס של מחלקת בת. לשם כך נדרשת המרה מפורשת, כי היא לא תמיד בטוחה:

Animal animal = new Dog();  // המרה כלפי מעלה
Dog dog = (Dog) animal;     // המרה כלפי מטה - נדרשת המרת טיפוס מפורשת
dog.bark();                 // כעת אפשר לגשת למתודות של Dog

המרה כלפי מטה היא מסוכנת. אם האובייקט אינו באמת מהסוג שאליו ממירים אותו, Java זורקת ClassCastException בזמן הריצה:

Animal animal = new Cat();
Dog dog = (Dog) animal;  // עובר קומפילציה, אבל קורס בזמן ריצה!

המהדר לא יכול לזהות את השגיאה הזאת כי הוא רואה רק את הטיפוסים המוצהרים. הטיפוס של האובייקט בפועל ידוע רק כשהתוכנית רצה. בשיעור הבא תלמד איך לבדוק בבטחה את הטיפוס של אובייקט לפני ביצוע המרה כלפי מטה.

challenge icon

אתגר

קל

בואו נבנה מערכת נגן מדיה שמדגימה בפועל גם המרת טיפוס כלפי מעלה וגם המרת טיפוס כלפי מטה. תיצור היררכיה של סוגי מדיה ותתרגל המרה בין הפניות למחלקת אב ולמחלקות יורשות.

תארגן את הקוד שלך בארבעה קבצים:

  • Media.java: צור מחלקת בסיס המשותפת לכל סוגי המדיה. לכל פריט מדיה יש שדה title (String). כלול בנאי לאתחול שלו, מתודת getter בשם getTitle(), ומתודה בשם play() שמדפיסה: Playing: [title]
  • Song.java: צור מחלקה שיורשת מ-Media. לשירים יש שדה נוסף בשם artist (String). השתמש ב-super לאתחול מחלקת האב. דרוס את play() כדי להדפיס: Playing song: [title] by [artist]. הוסף מתודה בשם showArtist() שמדפיסה: Artist: [artist]
  • Podcast.java: צור מחלקה נוספת שיורשת מ-Media. לפודקאסטים יש שדה בשם episode (int). דרוס את play() כדי להדפיס: Playing podcast: [title] - Episode [episode]. הוסף מתודה בשם showEpisode() שמדפיסה: Episode: [episode]
  • Main.java: הדגם המרות טיפוס כלפי מעלה וכלפי מטה עם סוגי המדיה שלך. תקבל ארבעה קלטים: שם של שיר, שם של אמן, שם של פודקאסט ומספר של פרק.

    תחילה, צור Song והמר אותו כלפי מעלה להפניה מסוג Media. קרא ל-play() באמצעות ההפניה הזו כדי לראות פולימורפיזם בזמן ריצה בפעולה.

    לאחר מכן, המר את הפניית ה-Media הזו כלפי מטה בחזרה ל-Song וקרא ל-showArtist() כדי לגשת למתודה הייחודית למחלקה היורשת.

    לאחר מכן, צור Podcast והמר אותו כלפי מעלה להפניה מסוג Media. קרא ל-play() באמצעות ההפניה הזו.

    לבסוף, המר את הפניית ה-Media הזו כלפי מטה בחזרה ל-Podcast וקרא ל-showEpisode().

תקבל ארבעה קלטים: שם השיר (String), שם האמן (String), שם הפודקאסט (String) ומספר הפרק (int).

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

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קראו את הקלטים
        String songTitle = scanner.nextLine();
        String artistName = scanner.nextLine();
        String podcastTitle = scanner.nextLine();
        int episodeNumber = scanner.nextInt();
        
        // TODO: צרו מופע של Song ובצעו לו המרת טיפוס כלפי מעלה להפניה מסוג Media
        
        // TODO: קראו ל-play() דרך ההפניה מסוג Media (מדגים פולימורפיזם)
        
        // TODO: בצעו המרת טיפוס כלפי מטה של ההפניה מסוג Media בחזרה ל-Song
        
        // TODO: קראו ל-showArtist() דרך ההפניה מסוג Song
        
        // TODO: צרו מופע של Podcast ובצעו לו המרת טיפוס כלפי מעלה להפניה מסוג Media
        
        // TODO: קראו ל-play() דרך ההפניה מסוג Media
        
        // TODO: בצעו המרת טיפוס כלפי מטה של ההפניה מסוג Media בחזרה ל-Podcast
        
        // TODO: קראו ל-showEpisode() דרך ההפניה מסוג Podcast
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Java אונליין