הורשה – Inheritance

בקטגוריה: פרוייקטים|שפות תכנות|תכנות מונחה עצמים

26 מרץ 2010

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

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

אם נחשוב על זה העולם לא מחולק רק לעצמים שונים ממחלקות שונות כמו מסך המחשב שלי, מסך המחשב שלך, שולחן הסלון שלי, העיפרון שלי וכדומה, אלא לפעמים יש ביניהם קשר של הורשה. אפשר לראות איזשהי הכלה מסויימת של אחד בתוך השני.
לדוגמה, למסך מחשב LCD ולמסך טלויזיה LCD יש הרבה מאוד במשותף, שניהם מסכי LCD ומכאן נובעות תכונות רבות עליהם. חוץ מזה יש גם מסך טלויזיה Plasma וCRT וגם לכל אלו משהו במשותף, כולם טלויזיות. לא רק זה, אלא גם שכל אלו הם מסכים!
דוגמה מאוד יפה לזה זה החלוקה של האדם של הטבע. כל בעל חיים מקוטלג לסוג, למשפחה, למחלקה, מערכה וכדומה. לדוגמה דוב קוטב הוא מסוג דוב, ממשפחת הדוביים, מסדרת הטורפים, ממחלקת היונקים, ממערכת המיתרניים וממלכת בעלי החיים. תוכלו לראות שלכל שכבה כזאת יש המון במשותף ולכן אוגדו לקבוצה.

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class Carnivore {
	public $legs = 4;
	public $speed_kmh = 10;
	public $eyes = 2;
	public $cover_type = 'Leather';
	public $cover_length_cm = 4;
	public $can_eat = array();
 
	public function __construct() {
	}
 
	public function eatable($eatable_thing) {
		if(is_array($eatable_thing)) {
			$this->can_eat = array_merge($this->can_eat, $eatable_thing);
		}
		else {
			$this->can_eat .= $eatable_thing;
		}
		return;
	}
 
}
 
class Bear extends Carnivore {
	public $cover_type = 'Fur';
	public $cover_length_cm = 5;
	public $can_eat = array('fish', 'rabbits');
	public $roar_volume_dba = 75;
 
	public function roar() {
		echo "Rooaarrr!!";
	}
 
	public function get_fish($amount = 1) {
		// Go to the river and get a fish
	}
 
	public function sleep($for_hrs = 6) {
		// Go to the cave and sleep
	}
 
}
 
class Polar_Bear extends Bear {
	public $cover_color = 'White';
	public $cover_length_cm = 10;
 
	public function get_fish($amount = 1) {
		// Break ice first and get fish from there
	}
 
	public function sleep($for_hrs = 9) {
		// Go to a lonley place and sleep
	}
 
}
 
$carnivore = new Carnivore();
echo $carnivore->cover_type; // Outputs Leather
echo is_a($carnivore, 'Carnivore') ? 'yes' : 'no'; // Outputs yes
echo is_a($carnivore, 'Bear') ? 'yes' : 'no'; // Outputs no
echo is_a($carnivore, 'Polar_Bear') ? 'yes' : 'no'; // Outputs no
 
$bear = new Bear();
echo $bear->cover_type; // Outputs Fur
echo is_a($bear, 'Carnivore') ? 'yes' : 'no'; // Outputs yes
echo is_a($bear, 'Bear') ? 'yes' : 'no'; // Outputs yes
echo is_a($bear, 'Polar_Bear') ? 'yes' : 'no'; // Outputs no
 
$polar_bear = new Polar_Bear();
echo $bear->cover_type; // Outputs Fur
echo is_a($polar_bear, 'Carnivore') ? 'yes' : 'no'; // Outputs yes
echo is_a($polar_bear, 'Bear') ? 'yes' : 'no'; // Outputs yes
echo is_a($polar_bear, 'Polar_Bear') ? 'yes' : 'no'; // Outputs yes

כרגיל נעבור על הקוד.
ראשית הצהרנו על מחלקה פשוטה שמייצגת טורף.
שנית הצהרנו על מחלקה שמייצגת דוב ומרחיבה את מחלקת הטורף (Bear extends Carnivore). במבט קליל נגלה שכתבנו כמה מאפיינים שכבר הוזכרו במחלקת הטורף. מה שיקרה בפועל זה שמחלקת הטורף תשוכפל ובכל מקום בו כתבנו משהו בשם חדש הוא יוחלף. הצהרנו כאן גם על מאפיין חדש לחלוטין וכמה פעולות חדשות שפשוט יתווספו.
שלישית הצהרנו על מחלקה שמייצגת דוב קוטב ומרחיבה את מחלקת הדוב. כאן הצהרנו על מחדש על מספר מאפיינים ופעולות ויקרה דבר זהה למה שקרה בנושא מחלקת הדוב והטורף.
לבסוף יצרתי אובייקט של כל אחת מהמחלקות, לשם הדוגמה הדפסתי את סוג הכיסוי של כל אחד מהאובייקטים והפלטים היו: Leather, Fur וFur. עוד דוגמה הייתה הפונקצייה is_a, שבודקת האם אובייקט הוא מופע של מחלקה מסויימת או בן של אותה מחלקה. הפלטים די ברורים.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Polar_Bear {
	public $legs = 4;
	public $speed_kmh = 10;
	public $eyes = 2;
	public $cover_type = 'Fur';
	public $cover_length_cm = 10;
	public $can_eat = array('fish', 'rabbits');
	public $roar_volume_dba = 75;
	public $cover_color = 'White';
 
	public function __construct() {
	}
 
	public function eatable($eatable_thing) {
		if(is_array($eatable_thing)) {
			$this->can_eat = array_merge($this->can_eat, $eatable_thing);
		}
		else {
			$this->can_eat .= $eatable_thing;
		}
		return;
	}
 
	public function roar() {
		echo "Rooaarrr!!";
	}
 
	public function get_fish($amount = 1) {
		// Break ice first and get fish from there
	}
 
	public function sleep($for_hrs = 9) {
		// Go to a lonley place and sleep
	}
 
}

למה כל זה טוב?

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

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

בהצלחה!

4 תגובות להורשה – Inheritance

סמלון

איתי סלע

28 מרץ, 2010 בשעה 10:04

מעולה מעולה מעולה.

סמלון

יונתן

5 אפריל, 2010 בשעה 14:57

תודה, מחכה לפוסט הבא :)

סמלון

אלרוי

17 ספטמבר, 2010 בשעה 13:36

מדהים ! תודה רבה~

סמלון

מור

2 נובמבר, 2010 בשעה 15:05

תודה רבה , סוף סוף מאמר מובן.

טופס התגובה

קצת עלי

שמי שי ואני בונה אתרים וכיום חותך (מקודד) ומתכנת.
אני עובד אל מול התקן העולמי של W3C, ומתכנת בשפת PHP תוך שימוש בטכנולוגיות עדכניות, תוך שמירה על קוד שניתן לתחזוקה.
בין כישורי נמנים: PHP, SQL, (X)HTML, CSS (2-3), XML, JavaScript ( + jQuery) ועוד.

Zend Certified Engineer

  • דניאל: אחלה של מאמר. [...]
  • Shay | Exalted Web: אין סיבה שיהיו תווים מוזרים. פשוט שמור הכל בutf8, כולל את הdatabase, הhtml והphp, ואל תשכח להריץ שאי [...]
  • יונתן: אין לך בעיה עם תווים בעברית מהמסד? כל מה שאני שולף מוצג לי בתווים מוזרים.. [...]
  • Shay | Exalted Web: שמחתי לעזור :) [...]
  • יהונתן|YtsWeb: שי,תודה רבה על המאמר. חיפשתי באמת איך לחלק את העמודים בצורה טובה ושלא יראו 1000 מספרים. [...]

פרוייקט תכנות מונחה עצמים

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

קצת מידע

אחלק לפניכם את האתר לשלושה נושאים:

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