חזרנו עם התוכנית שלנו שיוצרת ווינסטונים
אבל הוספתי טיפוס אובייקט חדש שנקרא Hopper (הופר).
אני מגדירה את הופר באותו אופן שהגדרתי את ווינסטון
התחלתי עם פונקציית בנאי, נתתי לו את אותם המאפיינים ואת המתודה draw
והמתודה talk, ואז הוספתי עוד מתודה שנקראת
hooray (הידד), כי הופר אוהב לחגוג, לעומת ווינסטון שלא אוהב את זה כלל.
בתחתית הפונקציה יצרתי שני אובייקטי הופר חדשים
שקראתי להם lilHopper ו- bigHopper
וציירתי אותם, וקראתי למתודה talk על אחד, ולמתודה hooray על האחר
זה די מגניב
אם נסתכל על הקוד הזה כאן למעלה
אולי תשימו לב לדבר מעניין.
הקוד עבור Hopper הוא מאוד דומה לקוד עבור Winston. בייחוד הסתכלו על הבנאי. זהו אותו קוד כמו הבנאי של ווינסטון.
וגם הפונקציה talk היא בדיוק אותו קוד כמו הפונקציה talk של ווינסטון.
ולשניהם יש פונקציית draw זהה
כך שיש הרבה דברים משותפים לשני טיפוסי האובייקטים האלו
וזה הגיוני, כי אתם מבינים ש-Hopper ו-Winston הם שני טיפוסי אובייקטים
דומים בעולם שלנו. אם תחשבו על העולם האמיתי
מחוץ למחשב, רוב טיפוסי האובייקטים חולקים
מאפיינים דומים עם טיפוסי אובייקטים אחרים.
כמו למשל בממלכת החי. כל החיות
דומות אחת לשניה בדרכים מסוימות. ויש לנו סוגים שונים של חיות
כמו למשל בני אדם. ולבני אדם יש דברים משותפים עם שאר עולם החי
אבל יש להם גם דברים שמשותפים רק עם בני אדם אחרים.
אז נוכל לומר
שחיה היא טיפוס של אובייקט שהטיפוס של בן אדם יורש ממנו פונקציונליות.
אנחנו לא מתחילים מאפס, אנו מוסיפים על הפונקציונליות שירשנו מהיותנו בעלי חיים.
למשל, כל בעלי החיים משמיעים קולות
אבל בני אדם משתמשים בשפה.
הרעיון הזה של ירושה
הוא מאוד שימושי גם בתכנות.
אנו יוצרים שרשרת של ירושת אובייקטים בקוד ה-Javascript שלנו.
כדי לעשות זאת תחשבו על
מה משותף לטיפוסי האובייקטים שלנו
נמציא לדבר המשותף שם
כי אנחנו הולכים ליצור טיפוס אובייקט חדש
שמייצג את אובייקט הבסיס.
הבה נקרא להם יצורים (creatures).
הם שניהם יצורים.
אז נאמר var Creature שווה.. ואז נרצה לשים את פונקציית הבנאי שלנו
אז בואו פשוט נגנוב את זאת של Hopper כי היא זהה גם לזו של Winston.
אוקיי.
ואז, בואו נראה..
עכשיו אנחנו רוצים..
מה נרצה לעשות עכשיו?
אולי אנחנו רוצים להוסיף את הפונקציה של דיבור (talk)
אז גם עבור מתודת talk נגנוב את של Hopper. אבל כמובן נרצה שהיא תהיה חלק מהאב טיפוס של היצור (creature) במקום.
אוקיי, יפה.
אז עכשיו יש לנו את טיפוס האובייקט של יצור.
אבל אנחנו צריכים לספר ל-Hopper שהוא צריך
לבסס את הפונקציונליות שלו על זו של Creature
נעשה זאת על ידי כך שנרשום את השורה הבאה
נרשום Hopper.prototype
שווה ל-Object.create
Creature.prototype
מה שהשורה הזו עושה הוא לספר ל-Javascript שצריך לבסס את אב הטיפוס של Hopper, כלומר את כל הפונקציונליות של Hopper, על אב הטיפוס של Creature.
זה אומר שבכל פעם שהשפה תחפש פונקציה של הופר, היא מחפשת קודם באב טיפוס של הופר,
אבל אחר כך, אם היא לא תמצא את הפונקציה היא תחפש אותה באב טיפוס של Creature.
הרעיון הזה נקרא שרשרת אבות טיפוס (prototype chain)
עכשיו, ברגע שעשינו זאת, אנחנו יכולים למחוק
את המתודה talk מ-Hopper
כי היא כבר קיימת אצל Creature
שנמצא גבוה יותר בשרשרת אבות הטיפוס.
מוכנים?
זה עבד!
זה עובד, כי מצאנו את הפונקציה באב הטיפוס של Creature במקום.
ננסה למחוק את הפונקציה הזו גם אצל ווינסטון.
אוקיי, זה לא עבד - אין לאובייקט מתודת talk.
מדוע? ובכן, יש לנו את הבנאי של ווינסטון
ואת המתודה draw, ומחקנו את talk.
שימו לב ששכחנו לספר גם לאב הטיפוס של ווינסטון
שעליו להתבסס על אב הטיפוס של יצור.
אז אנחנו צריכים את השורה החשובה הזו.
Winston.prototype שווה ל- Object.create
ואז בסוגריים Creature.prototype
יפה!
שימו לב למשהו חשוב
שמתי את השורה הזו אחרי פונקציית הבנאי, אבל לפני שאני מוסיפה כל דבר אחר
לאב הטיפוס של ווינסטון. זה מה שבדרך כלל תרצו לעשות.
אתם רוצים
לספר לאובייקט מיד בהתחלה
שזהו אב הטיפוס הראשוני שעליו האב טיפוס הנוכחי יהיה מבוסס
אבל אחר כך אנו מוסיפים עוד דברים לאב-טיפוס הזה
כי יכול להיות משהו שהוא ייחודי ל-Winston או ייחודי ל-Hopper
שאין לאובייקטי Creature.
זה ממש מגניב שאתם יכולים להגדיר כאלו דברים.
אוקיי. אם תסתכלו על זה, עדיין יש לנו קצת קוד שחוזר על עצמו
הקוד של הבנאי.
נכון? יש לנו אותו שלוש פעמים.
האם אנחנו יכולים פשוט למחוק אותו?
בואו ננסה.
אוקיי.. לא נראה שזה עבד
כי Hopper הופיע בפינה השמאלית העליונה, כאילו הוא שכח את כל המאפיינים שלו
זה כיוון ששפת Javascript לא מניחה שאתם רוצים את אותו בנאי, גם אם אתם רוצים לבסס את האב-טיפוס עליו
כך שניתן להגדיר בנאי משלנו לאובייקטים האלו.
אבל יש גם דרך קלה לקרוא לבנאי של אובייקט אחר
נעשה זאת כך:
(Creature.call(this, nickname, age, x, y
ראיתם, זה עבד. מה שזה עושה
זה לקרוא לבנאי של Creature.
זה קורא לפונקציה הזו, וזה אומר לקוד לקרוא לבנאי
כאילו הוא נקרא ישירות בתוך אובייקט Hopper
וכאילו הוא נקרא עם הפרמטרים האלו
אלו הם הפרמטרים שאיתם קראו ל-Hopper.
וזה פשוט יבצע את הקוד הזה כאילו הוא היה כאן בתוך הבנאי של האובייקט.
זה בדיוק מה שאנחנו רוצים, וזה עבד.
אנחנו יכולים
להעתיק את השורה הזאת גם לתוך
הבנאי של Winston.
וזה עובד. יופי!
אוקיי. תראו את זה. איחדנו את כל המאפיינים המשותפים והפונקציונליות המשותפת לתוך אובייקט בסיס יחיד, Creature
ויצרנו שני טיפוסי אובייקטים שמרחיבים את אובייקט הבסיס.
הם יורשים פונקציונליות, אבל הם גם מוסיפים דברים משלהם.
ומה שנחמד זה שאנחנו יכולים לשנות את הפונקציונליות המשותפת במקום אחד.
למשל אם נרצה לשנות את הגיל כמו קודם, נוכל לרשום '+' "yrs old"
עכשיו לכולם רשום "yrs old" אחרי הגיל שלהם.
או שאנחנו יכולים לשנות את המתודה talk, שיהיה כתוב "SUP"
ועכשיו כל ה-Winstonים וה-Hopperים אומרים "SUP". עכשיו כשראיתם איך ליצור טיפוסי אובייקטים ואיך לרשת מטיפוסי אובייקטים
אתם יכולים להתחיל לחשוב על איך זה יכול להיות שימושי בציורים, באנימציות, בסימולציות ובמשחקים.
לדוגמה, אולי יש לכם משחק ויש בו הרבה סוגי דמויות
וכולן יכולות לרוץ אבל רק חלקן יכולות לקפוץ
זהו מקום מושלם בשביל כמה טיפוסי אובייקטים ושימוש בירושה.
אבל אני בטוחה שאתם יכולים לחשוב על עוד הרבה שימושים אחרים.