מדריך לירושה בג'אווה

1. סקירה כללית

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

במילים פשוטות, ב- Java, מחלקה יכולה לרשת מחלקה אחרת וממשקים מרובים, בעוד ממשק יכול לרשת ממשקים אחרים.

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

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

ובסוף נראה מה זה אומר לרשת טיפוס.

2. הצורך בירושה

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

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

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

נבחין בשימוש במונחים מרובים כדי להתייחס לסוג שעובר בירושה מסוג אחר, במיוחד:

  • סוג בסיס נקרא גם סוג סופר או סוג הורה
  • סוג נגזר מכונה סוג מורחב, משנה או ילד

3. ירושה כיתתית

3.1. הרחבת כיתה

כיתה יכולה לרשת כיתה אחרת ולהגדיר חברים נוספים.

נתחיל בהגדרת מעמד בסיס אוטו:

גלגלים ברכב ציבורי {int; מודל מיתרים; בטל התחלה () {// בדוק חלקים חיוניים}}

הכיתה מכונית משוריינת יכול לרשת את חברי ה אוטו מחלקה על ידי באמצעות מילת המפתח מרחיב בהצהרתו:

מעמד ציבורי ArmoredCar מרחיב את המכונית {int bulletProofWindows; void remoteStartCar () {// ניתן להפעיל רכב זה באמצעות שלט רחוק}}

כעת אנו יכולים לומר כי מכונית משוריינת הכיתה היא תת-מחלקה של אוטו, והאחרון הוא מעמד-על של מכונית משוריינת.

שיעורים בג'אווה תומכים בירושה יחידה; ה מכונית משוריינת הכיתה לא יכולה להאריך מספר שיעורים.

כמו כן, שים לב כי בהעדר מרחיב מילת מפתח, מחלקה יורשת באופן מרומז מחלקה java.lang. אובייקט.

מעמד תת-מחלקה יורש את הלא-סטטי מוּגָן ו פּוּמְבֵּי חברים ממעמד מחלקת העל. בנוסף, החברים עם בְּרִירַת מֶחדָל ו חֲבִילָה הגישה עוברת בתורשה אם שתי הכיתות באותה חבילה.

מצד שני, ה פְּרָטִי ו סטָטִי חברי כיתה אינם עוברים בתורשה.

3.2. גישה לחברי הורים מכיתת ילדים

כדי לגשת למאפיינים או לשיטות שעברו בירושה, אנו יכולים פשוט להשתמש בהם ישירות:

מעמד ציבורי ArmoredCar מרחיב את המכונית {public String registerModel () {return model; }}

שים לב שאיננו זקוקים להתייחסות למעמד העל כדי לגשת לחבריו.

4. ירושת ממשק

4.1. יישום ממשקים מרובים

למרות ששיעורים יכולים לרשת מחלקה אחת בלבד, הם יכולים ליישם ממשקים מרובים.

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

ממשק ציבורי Floatable {void floatOnWater (); }
ממשק ציבורי מעופף {void fly (); }
מעמד ציבורי ArmoredCar מרחיב מכשירי רכב Floatable, Flyable {public void floatOnWater () {System.out.println ("אני יכול לצוף!"); } fly fly fly fly () {System.out.println ("אני יכול לעוף!"); }}

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

4.2. סוגיות בעלות ירושה מרובה

Java מאפשרת ירושה מרובה באמצעות ממשקים.

עד Java 7, זה לא היה בעיה. ממשקים יכולים רק להגדיר תַקצִיר שיטות, כלומר שיטות ללא כל יישום. כך שאם מחלקה הטמיע ממשקים מרובים עם אותה חתימת שיטה, זו לא הייתה בעיה. בסופו של דבר בכיתה המיישמת הייתה רק שיטה אחת ליישום.

בואו נראה כיצד משוואה פשוטה זו השתנתה עם כניסתה של בְּרִירַת מֶחדָל שיטות בממשקים, עם Java 8.

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

ג'אווה אינה מאפשרת ירושה של יישומים מרובים של אותן שיטות, המוגדרות בממשקים נפרדים.

הנה דוגמה:

ממשק ציבורי צף {תיקון חלל ברירת מחדל () {System.out.println ("תיקון אובייקט צף"); }}
ממשק ציבורי מעופף {תיקון חלל ברירת מחדל () {System.out.println ("תיקון חפץ מעופף"); }}
מעמד ציבורי ArmoredCar מרחיב מכשירי רכב Floatable, Flyable {// this not compile}

אם נרצה ליישם את שני הממשקים, נצטרך לעקוף את ה- לְתַקֵן() שיטה.

אם הממשקים בדוגמאות הקודמות מגדירים משתנים עם אותו שם, נניח מֶשֶׁך, איננו יכולים לגשת אליהם מבלי להקדים את שם המשתנה עם שם הממשק:

ממשק ציבורי צף {משך זמן = 10; }
ממשק ציבורי לעוף {משך זמן = 20; }
מעמד ציבורי ArmoredCar מרחיב מכשירי רכב Floatable, Flyable {public void aMethod () {System.out.println (משך זמן); // לא יחבר את System.out.println (Floatable.duration); // יציאות 10 System.out.println (Flyable.duration); // יציאות 20}}

4.3. ממשקים המרחיבים ממשקים אחרים

ממשק יכול להאריך מספר ממשקים. הנה דוגמה:

ממשק ציבורי Floatable {void floatOnWater (); }
ממשק ממשק מעופף {void fly (); }
ממשק ציבורי SpaceTraveller מרחיב Floatable, Flyable {void remoteControl (); }

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

5. סוג ירושה

כאשר כיתה יורשת מחלקה אחרת או ממשקים, מלבד בירושה של חבריהם, היא גם יורשת את סוגם. זה חל גם על ממשק שעובר בירושה ממשקים אחרים.

זהו מושג חזק מאוד, המאפשר למפתחים תוכנית לממשק (מחלקת בסיס או ממשק), במקום לתכנת ליישומים שלהם.

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

שכבה ציבורית עובד {שם מחרוזת פרטי; רכב פרטי לרכב; // קונסטרוקטור סטנדרטי}

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

עובד e1 = עובד חדש ("שרייא", שריון רכב חדש ()); עובד e2 = עובד חדש ("פול", SpaceCar חדש ()); עובד e3 = עובד חדש ("פאבני", BMW חדשה ());

6. חברי כיתה נסתרים

6.1. חברי מופע נסתר

מה יקרה אם גם מעמד העל וגם תת-מחלקה מגדירים משתנה או שיטה עם אותו שם? אל תדאג; אנחנו עדיין יכולים לגשת לשניהם. עם זאת, עלינו להבהיר את כוונתנו לג'אווה, על ידי קידומת המשתנה או השיטה למילות המפתח זֶה אוֹ סוּפֶּר.

ה זֶה מילת מפתח מתייחסת למופע בו היא משמשת. ה סוּפֶּר מילת מפתח (כפי שהיא נראית מובנת מאליה) מתייחסת למופע של כיתת האב:

מעמד ציבורי ArmoredCar מרחיב את המכונית {מודל מחרוזת פרטי; מחרוזת ציבורית getAValue () {return super.model; // מחזירה את ערך המודל שהוגדר בכיתת הבסיס Car // להחזיר this.model; // יחזיר ערך של המודל שהוגדר ב- ArmoredCar // מודל החזרה; // יחזיר ערך של המודל שהוגדר ב- ArmoredCar}}

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

6.2. חברים סטטיים נסתרים

מה קורה כאשר מחלקת הבסיס ומשכבות המשנה שלנו מגדירים משתנים ושיטות סטטיות עם אותו שם? האם אנו יכולים לגשת אל סטָטִי חבר ממעמד הבסיס, במחלקה הנגזרת, הדרך בה אנו עושים עבור משתני המופע?

בואו נגלה באמצעות דוגמא:

מכונית מחלקה ציבורית {מחרוזת סטטית ציבורית msg () {להחזיר "מכונית"; }}
מחלקה ציבורית ArmoredCar מרחיב את המכונית {מחרוזת סטטית ציבורית msg () {return super.msg (); // זה לא יהיה קומפילציה. }}

לא, אנחנו לא יכולים. החברים הסטטיים שייכים למעמד ולא למקרים. אז אנחנו לא יכולים להשתמש בלא סטטי סוּפֶּר מילת מפתח ב msg ().

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

החזר Car.msg ();

שקול את הדוגמה הבאה, בה גם מחלקת הבסיס וגם המחלקה הנגזרת מגדירים שיטה סטטית msg () עם אותה חתימה:

מכונית מחלקה ציבורית {מחרוזת סטטית ציבורית msg () {להחזיר "מכונית"; }}
מחלקה ציבורית ArmoredCar מרחיבה את המכונית {מחרוזת סטטית ציבורית msg () {return "ArmoredCar"; }}

כך נוכל לקרוא להם:

רכב ראשון = משוריין חדש (); שריון רכב שני = חדש שריון רכב ();

עבור הקוד הקודם, first.msg () תפלט "רכב ו second.msg () יפיק "ArmoredCar". ההודעה הסטטית שנקראת תלויה בסוג המשתנה שאליו מתייחסים מכונית משוריינת למשל.

7. מסקנה

במאמר זה סקרנו היבט מרכזי של שפת Java - ירושה.

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

כמו תמיד, קוד המקור המלא של הדוגמאות זמין ב- GitHub.