שיעורי מודול (1/2)
ממשקים
בעוד מחלקות מופשטות יכולות להכיל גם קוד מיושם חלקית וגם שדות מופעים, ממשקים ב-Java הם חוזים של התנהגות טהורה. ממשק מגדיר מה מחלקה חייבת להיות מסוגלת לעשות, אבל לא איך היא עושה זאת.
הדבר מאפשר ניתוק מוחלט בין הגדרת הפעולות לביצוען בפועל.
הגדרת ממשק (interface)
אנו משתמשים במילת המפתח interface. כל השיטות המוצהרות בממשק הן במרומז public ו-abstract (אין צורך לציין זאת):
interface Drivable {
void startEngine();
void stopEngine();
}הטמעת ממשק (implements)
מחלקה מיישמת ממשק באמצעות מילת המפתח implements ונדרשת לספק את היישום (עם גוף) עבור כל השיטות המוגדרות:
class Motorcycle implements Drivable {
@Override
public void startEngine() {
System.out.println("Rombo del motore acceso!");
}
@Override
public void stopEngine() {
System.out.println("Motore spento.");
}
}היתרונות של ממשקים
- ירושה מרובת: ב-Java, מחלקה יכולה להרחיב רק אחד מחלקת אב (ירושה יחידה), אך היא יכולה ליישם ממשקים מרובים בו-זמנית.
Java
class HybridCar implements Drivable, Chargeable { ... } - ניתוק: ניתן להגדיר משתנים באמצעות סוג הממשק. ניתן להקצות כל אובייקט שמיישם את הממשק הזה למשתנה כזה.
Java
Drivable vehicle = new Motorcycle(); vehicle.startEngine();
קבועים בממשקים
בממשקים אפשר להצהיר על שדות. שדות אלו הם באופן מרומז public static final (כלומר קבועי מחלקה), גם אם לא תציין את השינויים הללו. כתוצאה מכך, יש לאתחל אותם מיד עם ההכרזה:
interface PhysicsConstants {
double GRAVITY = 9.81; // Implicitly public static final
}שיטות ברירת מחדל (default)
החל מ-Java 8, ניתן להגדיר שיטות עם מימוש ברירת מחדל בתוך ממשק באמצעות מילת המפתח default. שיטות אלו אינן מאלצות את המחלקות המיישמות לעקוף אותן, ומספקות התנהגות סתירה:
interface Logger {
void log(String message);
// Default method with a body
default void logError(String message) {
log("ERROR: " + message);
}
}נסה זאת בעצמך
צור ממשק Flyable עם שיטת void fly() . לאחר מכן יישם מחלקה Bird שמטמיע את Flyable ומדפיס את Flying למסך.
הצג רמז
ב-Flyable, כתוב `void fly();`. במחלקה Bird, יישם את השיטה המסמנת אותה עם `@Override public void fly() { System.out.println('Flying'); }`.
הפתרון זמין לאחר 3 ניסיונות
הגדר ממשק Drawable עם שיטת draw() void. לאחר מכן יישם מחלקה Rectangle המיישמת Drawable ומדפיסה Drawing Rectangle.
הצג רמז
הגדר 'void draw();' בממשק. ב-Retangle, השתמש ב- `@Override public void draw() { System.out.println('Drawing Rectangle'); }`.
הפתרון זמין לאחר 3 ניסיונות
השלם את ממשק Swimmable על ידי הגדרת השיטה void swim() . לאחר מכן, השלימו את המחלקה Duck כך שתטמיע גם Flyable וגם Swimmable, הדפסת Flying in the fly() השיטה ו- Swimming in the swim() שיטה.
הצג רמז
הכריז על 'void swim();' בתוך Swimmable. הכריזו על 'class Duck מיישמת Flyable, Swimmable' והטמיעו את שתי השיטות בהדפסת המחרוזות המבוקשות.
הפתרון זמין לאחר 3 ניסיונות