Menu
Coddy logo textTech

מחלקות מופשטות

חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 25 מתוך 91.

מחלקה מופשטת היא מחלקה שלא ניתן ליצור ממנה מופע ישירות. היא משמשת כתבנית למחלקות אחרות, ומגדירה מתודות שמחלקות הבת חייבות לממש. יוצרים מחלקה מופשטת באמצעות מילת המפתח abstract.

<?php
abstract class Shape {
    protected $color;
    
    public function __construct($color) {
        $this->color = $color;
    }
    
    abstract public function calculateArea();
    
    public function getColor() {
        return $this->color;
    }
}

class Rectangle extends Shape {
    private $width;
    private $height;
    
    public function __construct($color, $width, $height) {
        parent::__construct($color);
        $this->width = $width;
        $this->height = $height;
    }
    
    public function calculateArea() {
        return $this->width * $this->height;
    }
}

$rect = new Rectangle("blue", 5, 3);
echo $rect->calculateArea();

פלט:

15

המחלקה Shape מצהירה על מתודה מופשטת calculateArea() בלי לספק לה מימוש. כל מחלקה שיורשת את Shape חייבת לממש את המתודה הזאת. שימו לב שמחלקות מופשטות יכולות להכיל גם מתודות רגילות כמו getColor(), שמחלקות יורשות מקבלות ישירות ממחלקת האב.

מתודות מופשטות מגדירות מה מחלקת צאצא חייבת לעשות, אך לא איך. כך מובטח שלכל הצורות תהיה מתודת calculateArea(), ובו בזמן כל צורה תוכל לחשב את השטח שלה באופן שונה.

נקודה מרכזית: מחלקות מופשטות משלבות את המבנה של ירושה עם דרישות מחייבות. השתמשו בהן כשרוצים לשתף קוד בין מחלקות קשורות, תוך הבטחה שכל מחלקת צאצא תממש מתודות מסוימות.

challenge icon

אתגר

קל

בואו נבנה מערכת נגן מדיה שמדגימה כיצד מחלקות מופשטות אוכפות חוזה, ובו בזמן מאפשרות לסוגי מדיה שונים לממש את אופן ההפעלה שלהם.

תארגנו את הקוד שלכם בשלושה קבצים:

  • Media.php: הגדירו מחלקה מופשטת בשם Media שמשמשת תבנית לכל סוגי המדיה. צריכה להיות לה תכונה מוגנת בשם $title ובנאי שמקבל את הכותרת ומגדיר אותה. כללו מתודה מופשטת בשם play() שמחלקות יורשות חייבות לממש. הוסיפו גם מתודה רגילה בשם getTitle() שמחזירה את הכותרת. המתודה הממומשת הזאת תעבור בירושה לכל המחלקות היורשות.
  • Song.php: הגדירו מחלקה בשם Song שיורשת את Media. כללו את קובץ Media בתחילת הקובץ. למחלקה הזאת יש תכונה נוספת בשם $artist. הבנאי צריך לקבל כותרת ושם אמן: השתמשו ב-parent::__construct() עבור הכותרת, ואז הגדירו בעצמכם את האמן. ממשו את המתודה הנדרשת play() כך שתחזיר את "Playing song: [title] by [artist]".
  • Podcast.php: הגדירו מחלקה בשם Podcast שיורשת את Media. כללו את קובץ Media בתחילת הקובץ. למחלקה הזאת יש תכונה נוספת בשם $episode (מספר שלם). הבנאי צריך לקבל כותרת ומספר פרק: השתמשו ב-parent::__construct() עבור הכותרת, ואז הגדירו את מספר הפרק. ממשו את המתודה הנדרשת play() כך שתחזיר את "Playing podcast: [title] - Episode [episode]".

בקובץ main.php, כללו גם את קובץ Song וגם את קובץ Podcast. תקבלו ארבעה ערכי קלט: כותרת השיר, שם האמן, כותרת הפודקאסט ומספר הפרק (בתור מחרוזת שיש להמיר למספר שלם). צרו אובייקט Song ואובייקט Podcast עם הערכים האלה. הדפיסו את התוצאה של קריאה ל-play() של השיר תחילה, ולאחר מכן של הפודקאסט, כל אחד בשורה משלו.

האתגר הזה מדגים כיצד מחלקות מופשטות מגדירות חוזה: לכל סוג מדיה חייבת להיות מתודה play(), אך כל סוג מממש אותה באופן שונה. אי אפשר ליצור מופע ישירות של המחלקה המופשטת Media; היא קיימת רק כדי לספק מבנה ופונקציונליות משותפת למחלקות היורשות שלה.

נסו בעצמכם

<?php
require_once 'Song.php';
require_once 'Podcast.php';

// קרא את הקלטים
$songTitle = trim(fgets(STDIN));
$artistName = trim(fgets(STDIN));
$podcastTitle = trim(fgets(STDIN));
$episodeNumber = intval(trim(fgets(STDIN)));

// TODO: צור אובייקט Song עם songTitle ו-artistName

// TODO: צור אובייקט Podcast עם podcastTitle ו-episodeNumber

// TODO: הדפס את התוצאה של קריאה ל-play() על השיר

// TODO: הדפס את התוצאה של קריאה ל-play() על הפודקאסט

?>
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר PHP אונליין