ממשקים
ממשק ב- Java הוא קצת כמו Class, אך עם הבדל משמעותי: interface
יכול להיות רק חתימות שיטות, שדות ושיטות ברירת מחדל. מאז Java 8, אתה יכול גם ליצור שיטות ברירת מחדל. בבלוק הבא תוכלו לראות דוגמה לממשק:
public interface Vehicle { public String licensePlate = ""; public float maxVel public void start(); public void stop(); default void blowHorn(){ System.out.println("Blowing horn"); } }
הממשק שלמעלה מכיל שני שדות, שתי שיטות ושיטת ברירת מחדל. לבד, אין בכך שימוש רב, אך בדרך כלל משתמשים בהם יחד עם שיעורים. אֵיך? פשוט, אתה צריך לוודא שהוא מחלק את implements
זה.
public class Car implements Vehicle { public void start() { System.out.println("starting engine..."); } public void stop() { System.out.println("stopping engine..."); } }
כעת, יש כלל בסיס : על המחלקה ליישם את כל השיטות בממשק. על השיטות להיות באותה חתימה בדיוק (שם, פרמטרים וחריגים) כמתואר בממשק. הכיתה אינה צריכה להכריז על השדות, אלא רק על השיטות.
מקרים של ממשק
ברגע שאתה יוצר מחלקת Java אשר implements
כל ממשק, ניתן להתייחס למופע האובייקט כמופע של הממשק. מושג זה דומה למושג של יישור ירושה.
// following our previous example Vehicle tesla = new Car(); tesla.start(); // starting engine ...
ממשק לא יכול להכיל שיטות קונסטרוקטור. לכן, אינך יכול ליצור מופע של ממשק עצמו. עליך ליצור מופע של מחלקה כלשהי המיישמת ממשק כדי להפנות אליו.
חשוב על ממשקים כטופס חוזה ריק, או תבנית.
מה אתה יכול לעשות עם תכונה זו? רב צורתיות! אתה יכול להשתמש בממשקים בלבד כדי להתייחס למופעי אובייקט!
class Truck implements Vehicle { public void start() { System.out.println("starting truck engine..."); } public void stop() { System.out.println("stopping truck engine..."); } } class Starter { // static method, can be called without instantiating the class public static void startEngine(Vehicle vehicle) { vehicle.start(); } } Vehicle tesla = new Car(); Vehicle tata = new Truck(); Starter.startEngine(tesla); // starting engine ... Starter.startEngine(tata); // starting truck engine ...
אבל מה לגבי ממשקים מרובים?
כן, אתה יכול ליישם ממשקים מרובים בכיתה אחת. בעוד שאתה בירושה במסגרת שיעורים הוגבלת לרשת מחלקה אחת בלבד, כאן תוכל להרחיב כל מספר ממשקים. אך אל תשכח ליישם את כל השיטות של כל הממשקים, אחרת ההידור ייכשל!
public interface GPS { public void getCoordinates(); } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } }
כמה תכונות של ממשקים
- אתה יכול למקם משתנים בתוך ממשק, אם כי זו לא תהיה החלטה הגיונית מכיוון ש- Classes אינם חייבים לקבל את אותו המשתנה. בקיצור, הימנעו מהצבת משתנים!
- כל המשתנים והשיטות בממשק הם ציבוריים, גם אם אתה משאיר את
public
מילת המפתח. - ממשק אינו יכול לציין את יישום שיטה מסוימת. זה תלוי בשיעורים לעשות את זה. אמנם היה חריג לאחרונה (ראה להלן).
- אם מחלקה מיישמת ממשקים מרובים, קיים סיכוי רחוק לחפיפה של חתימת השיטה. מכיוון שג'אווה אינה מתירה מספר שיטות של אותה חתימה בדיוק, הדבר עלול להוביל לבעיות. ראה שאלה זו למידע נוסף.
ממשק ברירת מחדל
לפני Java 8, לא הייתה לנו שום דרך להנחות ממשק לשם יישום שיטה מסוים. זה מוביל לבלבול רב ולהפסקות קוד אם הגדרת ממשק משתנה פתאום.
נניח שכתבת ספריית קוד פתוח המכילה ממשק. נגיד, הלקוחות שלך, כלומר כמעט כל המפתחים ברחבי העולם, משתמשים בזה בכבדות ושמחים. כעת נאלצתם לשדרג את הספרייה על ידי הוספת הגדרת שיטה חדשה לממשק כדי לתמוך בתכונה חדשה. אבל זה ישבור את כל המבנים שכן כל השיעורים המיישמים ממשק זה צריכים להשתנות כעת. איזה קטסטרופה!
למרבה המזל, Java 8 מספקת לנו כעת default
שיטות לממשקים. default
שיטה יכולה לכלול יישום משלה ישירות בתוך הממשק! לכן, אם מחלקה לא מיישמת שיטת ברירת מחדל, המהדר יבצע את היישום המוזכר בממשק. נחמד, לא? אז בספרייה שלך, אתה יכול להוסיף כל מספר של שיטות ברירת מחדל בממשקים מבלי לחשוש לשבור דבר!
public interface GPS { public void getCoordinates(); default public void getRoughCoordinates() { // implementation to return coordinates from rough sources // such as wifi & mobile System.out.println("Fetching rough coordinates..."); } } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } // no implementation of getRoughCoordinates() } Smartphone motoG = new Smartphone(); motog.getRoughCoordinates(); // Fetching rough coordinates...
אבל, מה קורה אם לשני ממשקים יש אותה חתימת שיטה?
שאלה מדהימה. במקרה כזה, אם לא תספק את היישום בכיתה, המהדר המסכן יתבלבל ופשוט ייכשל! עליכם לספק גם יישום שיטת ברירת מחדל בתוך הכיתה. יש גם דרך שימושית super
להתקשר לאיזה יישום אתה אוהב:
public interface Radio { // public void startRadio(); // public void stopRadio(); default public void next() { System.out.println("Next from Radio"); } } public interface MusicPlayer { // public void start(); // public void pause(); // public void stop(); default public void next() { System.out.println("Next from MusicPlayer"); } } public class Smartphone implements Radio, MusicPlayer { public void next() { // Suppose you want to call MusicPlayer next MusicPlayer.super.next(); } } Smartphone motoG = new Smartphone(); motoG.next(); // Next from MusicPlayer
שיטות סטטיות בממשקים
חדש גם ב- Java 8 הוא היכולת להוסיף שיטות סטטיות לממשקים. שיטות סטטיות בממשקים זהות כמעט לשיטות סטטיות בשיעורי בטון. ההבדל הגדול היחיד הוא static
ששיטות אינן עוברות בירושה בכיתות המיישמות את הממשק. המשמעות היא שהממשק מופנה כאשר קוראים לשיטה הסטטית ולא למחלקה המיישמת אותה.
interface MusicPlayer { public static void commercial(String sponsor) { System.out.println("Now for a message brought to you by " + sponsor); } public void play(); } class Smartphone implements MusicPlayer { public void play() { System.out.println("Playing from smartphone"); } } class Main { public static void main(String[] args) { Smartphone motoG = new Smartphone(); MusicPlayer.commercial("Motorola"); // Called on interface not on implementing class // motoG.commercial("Motorola"); // This would cause a compilation error } }
ירושת ממשק
אפשר גם ב- Java שממשק יירש ממשק אחר, באמצעות ניחוש נכון, extends
מילת מפתח:
public interface Player { public void start(); public void pause(); public void stop(); } public interface MusicPlayer extends Player { default public void next() { System.out.println("Next from MusicPlayer"); } }
כלומר, MusicPlayer
ממשק יישום המחלקה צריך ליישם את כל השיטות MusicPlayer
כמו גם Player
:
public class SmartPhone implements MusicPlayer { public void start() { System.out.println("start"); } public void stop() { System.out.println("stop"); } public void pause() { System.out.println("pause"); } }
אז עכשיו יש לך מושג טוב על ממשקי Java! עבור ללמוד על שיעורי מופשט כדי לראות כיצד Java נותנת לך דרך נוספת להגדיר חוזים.