JavaRush /בלוג Java /Random-HE /מנגנון עקיפת שיטה או Override ב-Java

מנגנון עקיפת שיטה או Override ב-Java

פורסם בקבוצה
שלום! אתה כבר משתמש בשיטות ב-Java ויודע עליהן רבות. סביר להניח שנתקלת במצב שבו היו שיטות רבות במחלקה אחת עם אותו שם אבל טיעונים שונים. אם אתה זוכר, באותם מקרים השתמשנו במנגנון העמסת יתר של השיטה. היום בואו נסתכל על מצב אחר. תארו לעצמכם שיש לנו שיטה אחת משותפת, אבל היא צריכה לעשות דברים שונים בהתאם לאיזו מחלקה היא נקראה. איך ליישם התנהגות זו? כדי להבין את זה, בואו ניקח כיתת הורים Animalשמציינת חיות וניצור בה שיטה voice- " קול ":
public class Animal {

   public void voice() {

       System.out.println("Voice!");
   }
}
למרות שזה עתה התחלנו לכתוב את התוכנית, סביר להניח שאתה יכול לראות את הבעיה הפוטנציאלית: יש הרבה בעלי חיים בעולם, וכולם "מדברים" אחרת: חתולים מיאו, ברווזים מקרקרים, נחשים שושנים. כיצד פועל מנגנון עקיפת השיטה - 2 המטרה שלנו היא פשוטה: להימנע מיצירת שלל שיטות להצבעה. במקום ליצור שיטות voiceCat()למיאו, voiceSnake()לשריקה וכו', אנחנו רוצים voice()שהנחש ישרש, החתול מיאו, והכלב ינבח כשקוראים לשיטה. נוכל להשיג זאת בקלות באמצעות מנגנון עקיפת השיטה (Override ב-Java) . ויקיפדיה נותנת את ההסבר הבא למונח "עקיפה": דחיפת שיטה בתכנות מונחה עצמים היא אחת התכונות של שפת תכנות המאפשרת לתת-מחלקה או מחלקה ילד לספק יישום ספציפי של שיטה שכבר מיושמת באחת ממחלקות העל. או כיתות הורים. זה, באופן כללי, נכון. עקיפה מאפשרת לך לקחת שיטה של ​​מחלקה אב ולכתוב יישום משלך של שיטה זו בכל מחלקה צאצאית. היישום החדש "יחליף" את ההורה בכיתת הילד. בוא נראה איך זה נראה עם דוגמה. בואו ניצור 4 כיתות ממשיכות לכיתה שלנו Animal:
public class Bear extends Animal {
   @Override
   public void voice() {
       System.out.println("Р-р-р!");
   }
}
public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void voice() {
       System.out.println("Woof!");
   }
}


public class Snake extends Animal {

   @Override
   public void voice() {
       System.out.println("Ш-ш-ш!");
   }
}
פריצת חיים קטנה לעתיד: כדי לעקוף את השיטות של מחלקת האב, עבור אל הקוד של המחלקה הצאצאית ב- Intellij IDE a, הקש Ctrl+O ובחר ב-“ Descendant methods... ” מהתפריט. תתרגלו להשתמש במקשי קיצור מההתחלה, זה יאיץ כתיבת תוכניות! כדי לקבוע את ההתנהגות שרצינו, עשינו כמה דברים:
  1. יצרנו שיטה בכל מחלקה צאצאית עם שם זהה למתודה במחלקת האב.
  2. אמרנו למהדר שקראנו לשיטה זהה לזה של מחלקת האב מסיבה: אנחנו רוצים לעקוף את ההתנהגות שלה. עבור ה"הודעה" הזו למהדר, שמנו הערת @Override על השיטה .
    ההערה @Override המוצבת מעל שיטה אומרת למהדר (וגם למתכנתים שקוראים את הקוד שלך): "הכל בסדר, זו לא טעות או השכחה שלי. אני זוכר ששיטה כזו כבר קיימת, ואני רוצה לעקוף אותה".

  3. כתבנו את היישום שאנחנו צריכים עבור כל כיתה צאצא. כשקוראים לו, נחש voice()צריך לשרוק, דוב צריך לנהום וכו'.
בוא נראה איך זה יעבוד בתוכנית:
public class Main {

   public static void main(String[] args) {

       Animal animal1 = new Dog();
       Animal animal2 = new Cat();
       Animal animal3 = new Bear();
       Animal animal4 = new Snake();

       animal1.voice();
       animal2.voice();
       animal3.voice();
       animal4.voice();
   }
}
פלט קונסולה: וואו! מיאו! ררר! ששש! מעולה, הכל עובד כמו שצריך! יצרנו 4 משתני התייחסות של מחלקת האב Animal, והקצנו אותם ל-4 אובייקטים שונים של המחלקות הצאצאים. כתוצאה מכך, כל חפץ מתנהג בצורה שונה. עבור כל אחת מהמחלקות הצאצאיות, השיטה שנדחפה voice()החליפה את השיטה "המקורית" voice()מהמחלקה Animal(שפשוט מוציאה "Voice!" לקונסולה). כיצד פועל מנגנון עקיפת השיטה - 3 לעקיפה יש מספר מגבלות:
  1. השיטה הנדרוסת חייבת להיות בעלת אותם ארגומנטים כמו שיטת האב.

    אם מתודה voiceבמחלקת אב מקבלת כקלט String, השיטה הנעקפת במחלקת הילד חייבת לקבל גם כקלט String, אחרת המהדר יזרוק שגיאה:

    public class Animal {
    
       public void voice(String s) {
    
           System.out.println("Voice! " + s);
       }
    }
    
    public class Cat extends Animal {
    
       @Override//error!
       public void voice() {
           System.out.println("Meow!");
       }
    }

  2. למתודה הנדחקת חייב להיות אותו סוג החזרה כמו שיטת האב.

    אחרת, נקבל שגיאת קומפילציה:

    public class Animal {
    
       public void voice() {
    
           System.out.println("Voice!");
       }
    }
    
    
    public class Cat extends Animal {
    
       @Override
       public String voice() {         //error!
           System.out.println("Meow!");
           return "Meow!";
       }
    }

  3. גם שינוי הגישה של שיטה שנדחקה לא יכול להיות שונה מה"מקורי":

    public class Animal {
    
       public void voice() {
    
           System.out.println("Voice!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void voice() {      //error!
           System.out.println("Meow!");
       }
    }
דחיפת שיטה בג'אווה היא אחד הכלים ליישום רעיון הפולימורפיזם (עקרון ה-OOP, עליו דיברנו בהרצאה האחרונה). לכן, היתרון העיקרי בשימוש בו יהיה אותה גמישות עליה דיברנו קודם. אנחנו יכולים לבנות מערכת פשוטה והגיונית של מחלקות, שלכל אחת מהן תהיה התנהגות ספציפית (כלבים נובחים, חתולים מיאו), אבל עם ממשק אחד - שיטה אחת voice()לכולם במקום שלל שיטות וכו' voiceDog().voiceCat()
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION