JavaRush /בלוג Java /Random-HE /שיטות ברירת מחדל בממשקים

שיטות ברירת מחדל בממשקים

פורסם בקבוצה
כל גרסה חדשה של Java שונה מהקודמת. הנה דוגמה לשינויים מהחומר שסקרנו: לפני Java 5, לא היו enumשמות בשפה.
שיטות ברירת מחדל בממשקים - 1
כמו כן, Java 8 שונה באופן ניכר מ-Java 7. רוב ההרצאות שלנו כתובות בגרסה השביעית של השפה, אך כמובן, לא נתעלם מחידושים חשובים. מכיוון שאנו מדברים על ממשקים בהרצאה זו, בואו נסתכל על עדכון אחד - שיטות ברירת מחדל בממשקים . אתה כבר יודע שממשק אינו מיישם . המשימה שלו היא לתאר איזו התנהגות צריכה להיות לכל האובייקטים שמיישמים אותו . אבל לעתים קרובות מפתחים נתקלו במצבים שבהם היישום של שיטה בכל המחלקות היה זהה. בואו נסתכל על הדוגמה של המכונית הישנה שלנו:
public interface Car {

   public void gas();

   public void brake();
}
public class Sedan implements Car {

   @Override
   public void gas() {
       System.out.println("Газ!");
   }

   @Override
   public void brake() {
       System.out.println("Тормоз!");
   }
}


public class Truck implements Car {

   @Override
   public void gas() {
       System.out.println("Газ!");
   }

   @Override
   public void brake() {
       System.out.println("Тормоз!");
   }
}


public class F1Car implements Car {
   @Override
   public void gas() {
       System.out.println("Газ!");
   }

   @Override
   public void brake() {
       System.out.println("Тормоз!");
   }
}
מה לדעתך הבעיה העיקרית בקוד הזה? בטח שמתם לב שכתבנו חבורה של אותו קוד! בעיה זו נפוצה בתכנות ויש להימנע ממנה. דבר נוסף הוא שלפני שחרורו של Java 8 לא היו אפשרויות פתרון מיוחדות. כשהגרסה הזו יצאה, אפשר היה להגדיר שיטות ברירת מחדל וליישם אותן ממש בתוך הממשק! הנה איך זה נעשה:
public interface Car {

   public default void gas() {
       System.out.println("Газ!");
   }

   public default void brake() {
       System.out.println("Тормоз!");
   }
}

public class Sedan implements Car {

}

public class Truck implements Car {

}

public class F1Car implements Car {

}
כעת השיטות gas()ו- brake(), שהיו זהות עבור כל המכונות, כלולות בממשק, ואין צורך בקוד כפול. יתרה מכך, השיטות זמינות בכל אחת מהשיעורים!
public class Main {

   public static void main(String[] args) {

       F1Car f1Car = new F1Car();
       Sedan sedan = new Sedan();
       Truck truck = new Truck();
       truck.gas();
       sedan.gas();
       f1Car.brake();
   }
}
מה אם יש 100 מחלקות עם שיטה gas(), אבל רק ל-99 מהן יש את אותה התנהגות? זה הורס הכל, ושיטת ברירת המחדל לא תעבוד במקרה הזה? כמובן שלא :) ניתן לעקוף שיטות ברירת מחדל של ממשקים.
public class UnusualCar implements Car {
   @Override
   public void gas() {
       System.out.println("Эта машина газует по-другому!");
   }

   @Override
   public void brake() {
       System.out.println("Эта машина тормозит по-другому!");
   }
}
כל שאר 99 סוגי המכונות יישמו את שיטת ברירת המחדל, והמחלקה UnusualCar- היוצא מן הכלל - לא תקלקל את התמונה הכוללת ותקבע את התנהגותה בשלווה. ירושה מרובה בממשקים כפי שאתה כבר יודע, אין ירושה מרובה ב-Java. יש לכך סיבות רבות, נבחן אותן בהרחבה בהרצאה נפרדת. בשפות אחרות, למשל, ב-C++, זה הפוך. ללא ירושה מרובה נוצרת בעיה רצינית: לאותו חפץ יכולים להיות מספר מאפיינים ו"התנהגויות" שונות. דוגמה מהחיים: בשביל ההורים שלנו אנחנו ילדים, בשביל המורים אנחנו סטודנטים, בשביל הרופאים אנחנו מטופלים. בחיים אנחנו מופיעים בתפקידים שונים ובהתאם לכך מתנהגים אחרת: ברור שנדבר עם מורים אחרת מאשר עם חברים קרובים. בואו ננסה לתרגם את המצב הזה לקוד. בואו נדמיין שיש לנו שני כיתות: בריכה ועופרי. בשביל בריכה צריך ציפורים שוחות, ולציפורה צריך מעופפים. לשם כך, יצרנו שתי מחלקות בסיס - FlyingBirdו Waterfowl.
public class Waterfowl {
}

public class FlyingBird {
}
בהתאם לכך, נשלח לעוף את הציפורים שמעמדן עובר בירושה FlyingBird, ואל הבריכה - אלה שיורדים מ Waterfowl. הכל נראה פשוט. אבל מה נעשה אם נצטרך לזהות את הברווז איפשהו? היא גם שוחה וגם עפה. אבל אין לנו ירושה מרובה. למרבה המזל, Java מספקת יישומים מרובים של ממשקים. אם כיתה לא יכולה לרשת מכמה הורים, יישום מספר ממשקים קל! הברווז שלנו יכול להיות גם מעופף וגם שוחה :) מספיק להשתמש בממשקים FlyingBirdולא Waterfowlבשיעורים כדי להשיג את התוצאה הרצויה.
public class Duck implements FlyingBird, Waterfowl {

   //методы обоих интерфейсов легко объединяются в одном классе

   @Override
   public void fly() {
       System.out.println("Летим!");
   }

   @Override
   public void swim() {

       System.out.println("Плывем!");
   }
}
הודות לכך, התוכנית שלנו שומרת על ניהול מחלקות גמיש, ובשילוב עם יישום שיטות ברירת מחדל, היכולת שלנו להגדיר את ההתנהגות של אובייקטים הופכת כמעט בלתי מוגבלת! :)
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION