בנית-אתרים.com – בלוג בנית אתרים
בקטגוריה: פרוייקטים|שפות תכנות|תכנות מונחה עצמים
5 אפר' 2010שים לב: הפוסט הזה מסתמך על ידע מפוסטים קודמים בסדרה, לאינדקס הפוסטים של תכנות מונחה עצמים.
כל הכבוד! הגעתם לנושאים המרתקים ביותר בתכנות מונחה עצמים. הסיבה האמיתית שכל העסק הזה משתלם, הפשטה ופולימורפיזם.
לפני שנכנס בדיוק למה זה כל אחד מהמושגים ננסה לראות אותם בעולם המוכר לנו.
דיברנו כבר על כך שיכול להיות לנו לדוגמה דוב קוטב, שכמובן יורש מדוב, שיורש בתורו מטורפים; אולם כשנחשוב על זה אין בטבע אובייקט שהוא טורף, נמצא רק כאלו ממחלקה שיורשת ממנה. התכונה הזו נקראת אבסטרקציה ("הפשטה").
אבל זה לא נגמר פה, כל טורף יכול לבצע פעולת טריפה, אבל כל אחד עושה את זה בדרך אחרת, אך כולם ללא יוצא מן הכלל יכולים לטרוף. תכונה זו נקראת פולימורפיזם ("רב צורתיות") – תוצאה ישירה של אבסטרקציה.
בתכנות ניתן להגדיר פעולות כאבסטרקטיות ובכך לא לכתוב את המימוש שלהן אלא רק את הגדרת הכימוס שלהן ואת הפרמטרים שלהן.
בכדי להצהיר על פעולה או על מחלקה כאבסטרקטית יש לכתוב את המילה abstract לפני ההוראה (לדוגמה: abstract class Bear).
כל מחלקה שיש בה פעולה אבסטרקטית אחת ומעלה חייבת להיות מוגדרת כאבסטרקטית בעצמה.
ניתן להגדיר מחלקות כאבסטרקטיות גם אם אין בהן פעולות אבסטרקטיות.
לא ניתן ליצור מופעים של מחלקה אבסטרקטית, אך כן ניתן לרשת ממנה.
מחלקה היורשת ממחלקה אבסטרקטית חייבת לממש את כל הפעולות האבסטרקטיות שהיא יורשת.
פולימורפיזם הוא מה שמאפשר לנו להתייחס לכמה אובייקטים – שמחלקותיהם יורשות מאותה מחלקה – בצורה דומה. כך שניתן להריץ את הפעולה eat עם אותם פרמטרים על אובייקטים של המחלקות Bear וLion, היורשות מהמחלקה Carnivore.
בשפות בהן יש להצהיר על משתנים ולציין את סוגם (כמו C, ASP.Net, Java וכו') יש לכך יתרון נוסף, ניתן להצהיר על משתנה מסוג Carnivore ולהציב בו אובייקט של המחלקה Lion! פשוט כי היא יורשת ממנו!
אתן דוגמה לישום פשוט שכולל מחלקות פשוטות שמנהלות databaseים מסוג MySQL וSQLite. נצא מתוך נקודת הנחה שיש לנו database עם טבלה pages שמכילה עמודת name וcontent.
היישום ישלוף דף לפי מה שמוגדר בget ויציג אותו, אם לא ימצא דף יציג הודעת שגיאה.
נכתוב את המחלקות:
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 | abstract class abstract_db { protected $con; abstract public function __construct($con_data); abstract public function query($query_string); abstract public function num_rows($query); abstract public function escape_string($string); abstract public function fetch($resource); abstract public function __destruct(); } class mysql_db extends abstract_db { public function __construct($con_data) { $this->con = mysql_connect($con_data['host'], $con_data['username'], $con_data['password']); mysql_select_db($con_data['database'], $this->con); } public function query($query_string) { return mysql_query($query_string, $this->con); } public function num_rows($query) { return mysql_num_rows($query); } public function escape_string($string) { return mysql_real_escape_string($string, $this->con); } public function fetch($resource) { return mysql_fetch_object($resource); } public function __destruct() { mysql_close($this->con); } } class sqlite_db extends abstract_db { public function __construct($con_data) { $this->con = sqlite_open($con_data['file']); } public function query($query_string) { return sqlite_query($query_string, $this->con); } public function num_rows($query) { return sqlite_num_rows($query); } public function escape_string($string) { return sqlite_escape_string($string); } public function fetch($resource) { return sqlite_fetch_object($resource); } public function __destruct() { sqlite_close($this->con); } } |
ראשית הצהרנו על מחלקה אבסטרקטית ולה מאפיין אחד שמחזיק את החיבור למסד הנתונים ו6 פעולות שכולן אבסטרקטיות.
שנית הצהרנו על מחלקה mysql_db המרחיבה את abstract_db ומימשנו בה את כל הפעולות. לבסוף כתבנו מחלקה sqlite_db דומה מאוד למחלקת mysql_db.
נכתוב את גוף היישום, (כך שישתמש בdatabase מסוג mysql):
1 2 3 4 5 6 7 8 9 | $db = new mysql_db(array('host' => 'localhost', 'username' => 'root', 'password' => '', 'database' => 'example')); $query = "SELECT name, content FROM pages WHERE name = '".$db->escape_string(array_key_exists('page', $_GET)?$_GET['page']:'index')."'"; $result = $db->query($query); if($db->num_rows($result) == 0) { exit('Invalid page!'); } $row = $db->fetch($result); echo '<h1>'.$row->name.'</h1>'; echo '<p>'.$row->content.'</p>'; |
השורה הראשונה יוצרת חיבור למסד נתונים מסוג mysql השנייה והשלישית מריצות שאילתה מאובטחת למציאת הדף. הרביעית, החמישית והשישית מונעות גישה לדפים שאינם קיימם. לבסוף שלפנו את תוצאות השאילתה והדפסנו את שם הדף ככותרת ואת התוכן בתוך פסקה.
בכדי לעבור לשימוש בsqlite בדרך כלל (אם לא היינו משתמשים בשכבת אבסטרקציה בדומה לזו) היינו צריכים לעבור שורה שורה ולהחליף את כל הפקודות mysql_* לפקודות הsqlite המתאימות להן; אך ביישום הזה כל שעלינו לעשות זה להחליף את השורה הראשונה לזו:
$db = new sqlite_db(array('file' => 'example.db'));
זהו זה, זה הכל!
כפי שאתם רואים מעבר לתכנות מונחה עצמים יוצר קוד מסודר יותר ונקי יותר המאפשר דינאמיות גבוהה יותר בזכות תכונות הכימוס, הורשה, אבסטרקציה ופולימורפיזם שאינן קיימות בתכנות פרוצדורלי.
כאן אמור להסתיים הפרוייקט אך למעשה זהו סופו של העיקר, אך לא הכל. מספר מאמרים נוספים יתווספו וימשיכו מכאן והלאה.
בהצלחה!
שמי שי ואני בונה אתרים וכיום חותך (מקודד) ומתכנת.
אני עובד אל מול התקן העולמי של W3C, ומתכנת בשפת PHP תוך שימוש בטכנולוגיות עדכניות, תוך שמירה על קוד שניתן לתחזוקה.
בין כישורי נמנים: PHP, SQL, (X)HTML, CSS (2-3), XML, JavaScript ( + jQuery) ועוד.
2 תגובות להפשטה ופולימורפיזם – Abstraction and Polymorphism
איתי סלע
7 אפריל, 2010 בשעה 18:16
שי, לפני שאתחיל להתעמק במאמר: טעות חמורה בפייך.
פולימורפיזם היא אומנם תוצאה של חשיבה אבסטרקטית אבל היא איננה מקושרת באופן ישיר למחלקה אבסטרקטית.
למעשה יש לך חוסר ידע קריטי פה. לחוסר הידע הזה קוראים interface. מה שאתה תיארת כמחלקה אבסטרקטית זה למעשה interface.
ההבדל בין interface למחלקה אבסטרקטית הוא שבמחלקה אבסטרקטית אתה -כן- יכול לממש חלק מהפונקציות ולהוריש אותן(וכן גם חלק לא ללממש ואז המחלקה היורשת תהיה חייבת לממשן).
עוד נקודה חשובה ביותר: ניתן לממש מספר רק של interfaceים אך ניתן לרשת רק ממחלקה אבסטקטית(או רגילה) אחת.
interface:
מימושים מרובים.
אין הרשאות גישה שאינן public.
לא ניתן לכתוב תוכן בפונקציות.
מחלקה אבסטרקטית:
הורשה יחידה.
ניתן לממש פונקציות כבר במחלקה.
תקרוא עוד בנושא. זה אחד החלקים היותר מבלבלים למתחילים. מה ההבדל ומתי להשתמש בinterface ומתי במחלקה אבסטרקטית.
אני מציין שוב: מה שתיארת פה זה התנהגות של interface – למחלקה אבסטרקטית יש עוד יכולות!
Shay | Exalted Web
7 אפריל, 2010 בשעה 19:20
אתה צודק לחלוטין, ולמעשה אני יודע את זה. הדוגמה לא הייתה כל כך טובה.
בגדול interface זה כמו להגיד אתה חייב לממש את הפונקציות האלו.
יטופל, תודה על התגובה!