ממשק לעומת מחלקה מופשטת
חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 30 מתוך 91.
עכשיו, לאחר שלמדת על ממשקים ועל מחלקות מופשטות, נבהיר מתי להשתמש בכל אחד מהם. הם עשויים להיראות דומים, אך הם משמשים למטרות שונות ובעלי יכולות ייחודיות.
| תכונה | ממשק | מחלקה מופשטת |
|---|---|---|
| מתודות | חתימות של מתודות בלבד | מתודות מופשטות וממומשות |
| מאפיינים | קבועים בלבד | יכולה לכלול מאפיינים |
| ירושה מרובה | מחלקה יכולה לממש כמה ממשקים | מחלקה יכולה לרשת רק ממחלקה אחת |
| בנאי | אפשר להצהיר על חתימת __construct (ללא גוף) | אפשר להגדיר בנאי עם גוף |
השתמשו בממשק כשרוצים להגדיר חוזה שמחלקות שאינן קשורות זו לזו יכולות לממש. לדוגמה, גם Printer וגם Logger עשויות לממש ממשק Writable, אף שאין להן אב משותף.
השתמשו במחלקה מופשטת כשיש לכם מחלקות קשורות שחולקות קוד משותף. אם גם המחלקות Dog וגם Cat צריכות את אותה מימוש של המתודה eat(), מחלקת Animal מופשטת מאפשרת לכם לכתוב את הקוד הזה פעם אחת.
אפשר גם לשלב בין שתי הגישות. מחלקה יכולה לרשת ממחלקה מופשטת ובו בזמן לממש כמה ממשקים:
<?php
abstract class Animal {
protected $name;
public function eat() {
return $this->name . " is eating";
}
}
interface Swimmable {
public function swim();
}
class Duck extends Animal implements Swimmable {
public function __construct($name) {
$this->name = $name;
}
public function swim() {
return $this->name . " is swimming";
}
}
נקודה מרכזית: בחרו בממשקים כדי להגדיר יכולות בין מחלקות שאינן קשורות זו לזו. בחרו במחלקות מופשטות כשאתם צריכים לשתף קוד בין מחלקות קשורות.
אתגר
קלבואו נבנה מערכת כלי רכב שמדגימה מתי להשתמש במחלקה מופשטת לעומת ממשק, ואיך לשלב ביעילות בין שתי הגישות.
תיצרו מערכת שבה כלי רכב חולקים מאפיינים משותפים באמצעות ירושה, אך יכולים גם לקבל יכולות נוספות באמצעות ממשקים. הדבר משקף החלטות תכנון מהעולם האמיתי: מכונית "is a" כלי רכב (ירושה), אך יש לה גם "has the capability" לתדלק (ממשק).
ארגנו את הקוד שלכם בארבעה קבצים:
Refuelable.php: הגדירו ממשקRefuelableעם חתימת מתודה יחידה:refuel($amount). יכולת זו יכולה להתאים לכל מחלקה שזקוקה לתדלוק, ללא קשר להיררכיית הירושה שלה.Vehicle.php: הגדירו מחלקה מופשטתVehicleשמספקת פונקציונליות משותפת לכל כלי הרכב. צריכה להיות לה תכונה מוגנת$brandותכונה מוגנת$fuelLevel(שמתחילה ב-0). הבנאי מקבל את שם המותג. כללו מתודה קונקרטיתgetBrand()שמחזירה את המותג, מתודה קונקרטיתgetFuelLevel()שמחזירה את רמת הדלק הנוכחית, ומתודה מופשטתdrive()שמחלקות הצאצא חייבות לממש.Car.php: צרו מחלקהCarשמרחיבה אתVehicleומממשת אתRefuelable. כללו את שני הקבצים הנדרשים בראש הקובץ. הבנאי מקבל את המותג ומעביר אותו לבנאי של מחלקת האב. ממשו אתdrive()כך שתחזיר"[brand] car is driving". ממשו אתrefuel($amount)כך שתוסיף את הכמות לרמת הדלק ותחזיר"[brand] refueled to [fuelLevel] liters".main.php: כללו את קובץ Car. תקבלו שתי קלטים: שם מותג וכמות דלק (המירו למספר שלם). צרוCarעם המותג. הדפיסו את התוצאה שלdrive()בשורה הראשונה, ואז הדפיסו בשורה השנייה את התוצאה שלrefuel()עם כמות הדלק.
האתגר הזה ממחיש את ההבחנה העיקרית: המחלקה המופשטת Vehicle משתפת קוד ומבססת קשר של "סוג של", בעוד שממשק Refuelable מוסיף יכולת שיכולה להתאים למחלקות אחרות שאינן קשורות (כמו גנרטור או סירה), בלי לדרוש מהן להיות כלי רכב.
נסו בעצמכם
<?php
require_once 'Car.php';
// קרא את הקלט
$brand = trim(fgets(STDIN));
$fuelAmount = intval(trim(fgets(STDIN)));
// TODO: צור Car עם המותג
// TODO: הדפס את התוצאה של drive() בשורה הראשונה
// TODO: הדפס את התוצאה של refuel() עם כמות הדלק בשורה השנייה
?>השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח $thisמתודותמאפייניםבנאי (__construct)הורס (__destruct)חזרה: מחשבון פשוט4ירושה
ירושה בסיסיתמילת המפתח parent::דריסת מתודותמילת המפתח finalמחלקות מופשטותסיכום – היררכיית עובדים7כימוס
ציבורי, מוגן, פרטימפרטי גישה לעומקמתודות גישה ועדכוןהסתרת מידעקידום פרמטרים בבנאי (8.0)סיכום – מערכת רישומי תלמידים2מרחבי שמות וטעינה אוטומטית
מבוא למרחבי שמותמילת המפתח useתקן הטעינה האוטומטית PSR-4הטוען האוטומטי של Composerסיכום – פרויקט מאורגן5ממשקים וחוזים
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםממשק לעומת מחלקה מופשטתרמזי טיפוסים עם ממשקיםסיכום - מחשבון צורות8מתודות קסם
מבוא למתודות קסם__toString ו־__debugInfo__get, __set, __isset, __unset__call ו־__callStatic__clone ושיבוט אובייקטים__serialize ו־__unserializeסיכום – אוסף מותאם אישית3מאפייני מחלקה
מאפייני מופע לעומת מאפיינים סטטייםקבועים במחלקותמתודות ומאפיינים סטטייםמאפיינים פרטיים ומוגניםמאפיינים לקריאה בלבד (PHP 8.1)סיכום – מנהל חשבון בנק6פולימורפיזם
בחינה מחדש של דריסת מתודותפולימורפיזם באמצעות ממשקיםרמזי טיפוסים וטיפוסי איחודקישור סטטי מאוחרסיכום — מעבד תשלומיםתרגלו בעצמכם: קומפיילר PHP אונליין