נגישות       נגישות
שינוי גודל טקסט:
א א א
שינוי צבעי האתר:
? מקשי קיצור:

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

הפעלת מקשי הקיצור תלויה בדפדפן שבו אתם משתמשים.

Internet Explorer, Chrome ובגרסאות ישנות של Firefox: לחצו על מקש Alt ועל מקש המספר או האות על-פי הרשימה. ב Firefox 3 ומעלה: לחצו על המקשים Alt + Shift + המספר או האות.

S - עבור לתוכן הדף
L - חיפוש
1- עמוד הבית
2 - פרוייקטים
3 - מדריכים
4 - אודות
5 - צרו קשר
6 - הצהרת נגישות
 

מתי והיכן להשתמש ב-traits?

מחבר:
בתאריך:

ב-PHP מותר לרשת ממחלקה אחת בלבד, אבל לעיתים אנחנו צריכים לרשת את הקוד שלנו מיותר ממקור אחד. במקרים כאלה, ניתן להוסיף עוד ועוד הורים לשרשרת ההורשה. הבעיה היא שאנו עלולים בקלות להגיע לשרשרת הורשה ארוכה שמסבכת את העניינים, ובאופן כללי עדיף לא לחרוג מיותר משלושה דורות של הורשה. דרך נוספת להתמודדות עם אותה בעיה היא באמצעות הכללת הקוד שאנו זקוקים לו (באמצעות include או require) ישירות לתוך המחלקה. גישה זו היא אומנם כשרה אבל מעט מסריחה.

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

 

eBook cover The essentials of Object Oriented PHP

 

כיצד trait עובד?

Trait דומה למחלקה בזה שהוא מקבץ קוד. התחביר לדוגמה:

trait TraitName {
  // trait code
}

בדוגמה הבאה, trait ששמו Price מחזיק את המתודה ששמה changePriceByDollars, שמחשבת את המחיר החדש מהישן, תוך התחשבות בשינוי המחיר בשקלים.

trait Price {
  public function changePriceByDollars($price, $change)
  {
    return $price + $change;
  }
}

אחרי שיצרנו את ה-trait, אנו יכולים להשתמש בו במחלקות באמצעות מילת המפתח use. בדוגמה הבאה, שתי המחלקות, Bmw ו-Mercedes משתמשים ב-Trait.

class Bmw {
  use Price;
}
 
class Mercedes {
  use Price;
}

כדי לראות את הקוד בפעולה, ניצור אובייקטים מהמחלקות, ואז נשתמש במתודה changePriceByDollars, שאותה הם קיבלו מה-trait.

$bmw1 = new Bmw();
// Add 3000$
echo $bmw1 -> changePriceByDollars(45000, +3000);
 
$mercedes1 = new Mercedes();
// Subtract 2100$
echo $mercedes1 -> changePriceByDollars(42000, -2100);

תוצאה:

48000
39900

מהדוגמה הזו אנו יכולים ללמוד שניתן להשתמש בקוד מה-trait במחלקות באותה הקלות שבה משתמשים ב-include.

 

האם מחלקות יכולות להשתמש ביותר מ-trait אחד?

מחלקה יכולה להשתמש ביותר מ-trait אחד, הרי לשם כך הומצאו ה-traits. כדי להדגים זאת, בואו נוסיף לקוד trait נוסף ששמו SpecialSell, ובו מתודה ששמה annonunceSpecialSell, שמודיעה על מכירות מיוחדות. בואו נראה כיצד האובייקט שיצרנו מהמחלקה Mercedes יכולה להשתמש בשני ה-trait-ים.

trait Price {
  public function changePriceByDollars($price, $change)
  {
    return $price + $change;
  }
}
  
trait SpecialSell {
  public function annonunceSpecialSell ()
  {
    return __CLASS__ . " on special sell";
  }
}
  
  
class Mercedes {
  use Price;
  use SpecialSell;
}
  
$mercedes1 = new Mercedes();
// Subtract 2100$
echo $mercedes1 -> changePriceByDollars(42000, -2100);
echo $mercedes1 -> annonunceSpecialSell();

תוצאה:

39900
Mercedes on special sell

 

כיצד trait שונה מהורשה רגילה?

Trait-ים משתמשים בצורה מיוחדת של הורשה שמאפשרת להם לכלול קוד ממספר traitים. צורה זו של הורשה מכונה הורשה אופקית (horizontal inheritance), והיא זו שמאפשרת את הכללת הקוד מה-trait במחלקות היורשות. זה דומה לשימוש בפקודות require או include, אבל נראה הרבה יותר מסודר.

בניגוד להורשה רגילה, שבה ניתן לרשת ממחלקה אחת בלבד, ניתן לרשת ממספר trait-ים.

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

כדאי לשים לב לעובדה ש-trait אינו מכבד את הכימוס של המשתנים והמתודות, ולפיכך אפשר לגשת ללא בעיה ממתודות שיורשים מה-trait גם למתודות ולמשתנים פרטיים במחלקה היורשת. בדוגמה להלן, המתודה changePriceByDollars שנורשה מה-trait יכולה לעבוד ללא בעיה עם המשתנה price למרות שהוא משתנה פרטי.

trait Price {
  // The method needs the $price property.
  public function changePriceByDollars($change)
 {
    return $this -> price += $change;
 }
}
 
 
class Mercedes {
  use Price;
 
  // The $price is private.
  private $price;
  
  public function __construct($price)
  {
    $this -> price = $price;
  }
  
  public function getPrice()
  {
    return $this -> price;
  }
}
  
  
$mercedes1 = new Mercedes(42000);
echo $mercedes1 -> getPrice();
$mercedes1 -> changePriceByDollars(-2100);
echo $mercedes1 -> getPrice();

תוצאה:

42000
39900

מדוגמה זו אנו יכולים ללמוד שלמתודה שנמצאת בתוך ה-trait יש גישה לתכונות ולמתודות פרטיים בתוך הקלאס שירש אותו.

 

מה יתרונות השימוש ב-trait?

Trait –ים מאפשרים למחלקות להשתמש בקוד מיותר ממקור אחד, ובכך, מאפשר לנו לעקוף את המגבלה של ירושה ממחלקה אחת בלבד.

 

מה חסרונות השימוש ב-traits?

בגלל האופי פורץ הגבולות של ה-trait, כדאי להיזהר משכפול הקוד בין trait-ים שונים, ומהתנגשות בין שמות המשתנים והפונקציות מהמקורות השונים.

כדאי לשים לכך שהשימוש ב-trait –ים עלול להתדרדר בקלות לשימוש לרעה, ולגרום לקוד שבנוי מטלאים על גבי טלאים, במקום קוד מתוכנן היטב שיוצרים באמצעות הורשה היררכית מסודרת.

 

באילו מקרים כדאי במיוחד להשתמש ב-trait?

במקרים מסוימים השימוש ב-traits יכול להוכיח את עצמו עדיף על הורשה רגילה. לדוגמה, כאשר מספר מחלקות מיישמות את אותו interface ולפיכך יורשות את הקוד שלו, אבל רק חלק מאותן המחלקות (ולא כולן) צריכות חלקים של הקוד. זה הגיוני להשתמש בהורשה רגילה לאותם המתודות שחולקות כל המחלקות, בעוד עדיף להשתמש ב-trait-ים עבור אותם מתודות שצריך רק בחלק מהמחלקות. לדוגמה, אם יש לנו שלוש מחלקות שיורשות את ה-interface ששמו Car (Bmw, Mercedes, Audi), ואנחנו צריכים את המתודה שמטפלת במכירה מיוחדת רק בשתיים מהמחלקות, נאמר על ה-Bmw וה-Mercedes בלבד, נעדיף להשתמש לשם כך ב-trait, כדי שהקוד ישותף רק בין המחלקות שצריכות אותו.

 

לסיכום

המסקנה שלנו מכל מה שראינו במדריך היא ש-trait מאפשר הכללת קוד ממספר מקורות, ולפיכך יכול לסייע לנו רבות, כל עוד נשתמש בו היכן שצריך.

 

המדריך מבוסס על "The essentials of Object Oriented PHP" שמלמד PHP מונחה עצמים באמצעות דוגמאות ותרגילים הקליקו על התמונה כדי לרכוש את ה-eBook:

eBook cover The essentials of Object Oriented PHP

 

לכל מדריכי ה-PHP מונחה עצמים

 

הוסף תגובה חדשה

 

= 6 + 9