Menu
Coddy logo textTech

קישור סטטי מאוחר

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

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

שקול את הדוגמה הזו, שבה self:: לא פועל כמצופה:

<?php
class ParentClass {
    public static function create() {
        return new self();
    }
    
    public static function getClassName() {
        return self::class;
    }
}

class ChildClass extends ParentClass {}

$obj = ChildClass::create();
echo get_class($obj) . "\n";
echo ChildClass::getClassName();

פלט:

ParentClass
ParentClass

למרות שקראנו ל־ChildClass::create(), קיבלנו אובייקט ParentClass, כי self:: נפתר בזמן ההידור. עכשיו נשתמש במקום זאת ב־static:::

<?php
class ParentClass {
    public static function create() {
        return new static();
    }
    
    public static function getClassName() {
        return static::class;
    }
}

class ChildClass extends ParentClass {}

$obj = ChildClass::create();
echo get_class($obj) . "\n";
echo ChildClass::getClassName();

פלט:

ChildClass
ChildClass

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

נקודה חשובה: השתמשו ב-static:: במקום ב-self:: כשרוצים שמחלקות יורשות יירשו ויתאימו אישית התנהגות סטטית כראוי.

challenge icon

אתגר

קל

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

תארגנו את הקוד בארבעה קבצים:

  • Model.php: צרו מחלקת בסיס Model עם מאפיין סטטי מוגן $tableName שערכו "models". הוסיפו מתודה סטטית create() שמשתמשת ב-new static() כדי להחזיר מופע חדש של המחלקה שקראה לה. הוסיפו מתודה סטטית נוספת getTable() שמחזירה את static::$tableName. לבסוף, הוסיפו מתודה describe() שמחזירה את "[ClassName] from table [tableName]" באמצעות static::class ו-static::$tableName.
  • User.php: צרו מחלקת User שיורשת את Model. כללו את קובץ מחלקת האב. דרסו את המאפיין הסטטי $tableName והגדירו את ערכו ל-"users". המחלקה יורשת את כל המתודות מ-Model ללא שינויים.
  • Product.php: צרו מחלקת Product שיורשת את Model. כללו את קובץ מחלקת האב. דרסו את המאפיין הסטטי $tableName והגדירו את ערכו ל-"products". גם כאן, המחלקה יורשת את כל המתודות ממחלקת האב.
  • main.php: כללו את הקבצים של User ושל Product. השתמשו במתודת המפעל המורשת create() כדי ליצור מופעים גם של User וגם של Product. עבור כל מופע, קראו ל-describe() והדפיסו את התוצאה בשורה נפרדת. לאחר מכן, הדפיסו את שם הטבלה של כל מחלקה באמצעות User::getTable() ו-Product::getTable(), כל אחד בשורה נפרדת.

הקסם כאן הוא שהמתודות create() ו-getTable() מוגדרות רק במחלקת האב Model, ובכל זאת הן פועלות כראוי עם מחלקות יורשות, משום ש-static:: דוחה את הקישור עד לזמן הריצה. כשתקראו ל-User::create(), PHP תיצור מופע של User, ולא מופע של Model, משום ש-static:: מתייחס למחלקה שנקראה בפועל.

הפלט שלכם אמור להציג ארבע שורות: התיאור של מופע User, התיאור של מופע Product, שם הטבלה של User ושם הטבלה של Product.

נסו בעצמכם

<?php

require_once 'User.php';
require_once 'Product.php';

// TODO: השתמשו במתודת המפעל create() שעברה בירושה כדי ליצור מופע של User

// TODO: השתמשו במתודת המפעל create() שעברה בירושה כדי ליצור מופע של Product

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

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

// TODO: הדפיסו את User::getTable()

// TODO: הדפיסו את Product::getTable()

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

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

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

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