interface שימושים ומטרה - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

interface שימושים ומטרה


bdoron

Recommended Posts

יש נושא שתמיד לא הבנתי

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

הרי כל הקטע זה ליצור הורשה מרובת

כי בהורשה רגילה מחלקה לא יכולה לרשת ממספר מחלקות

הבעיה שקשה לי להבין מה הקטע של האינטרפייס

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

אבל באינטרפייס אין לי מימוש באינטרפייס עצמו

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

אבל בכללי אינטרפייס אל חוסך לי בכלום,

קישור לתוכן
שתף באתרים אחרים

נראה לי ש-#C, לא שזה משנה. הרעיון הוא אותו רעיון.

ממשק זה הדרך של המחלקה שלך לומר "אני יודעת לעשות x,y,z". זה מאפשר למחלקות/פונקציות אחרות להשתמש בה בלי לדעת שום דבר על המימוש הפנימי שלה.

לדוגמה: נניח שלמחלקה שלך קוראים MyClass. אתה מחזיק רשימה של איברים מהמחלקה - <List<MyClass. עכשיו, אתה רוצה למיין את הרשימה הזו. איזה יופי - יש ל-List פונקציה בשם Sort! אבל רגע, איך List.Sort יודעת לפי מה למיין את הרשימה? היא צריכה לדעת איך להשוות בין שני אובייקטים מטיפוס MyClass. אז רק צריך ש-MyClass תממש פונקציה בשם CompareTo, שתקבל אובייקט אחר מסוג MyClass ואז תחזיר מי מהם גדול יותר. עכשיו List.Sort יכולה פשוט להשתמש בפונקציה הזו כדי להשוות בין האובייקטים. אבל רגע.... איך היא יודעת של-MyClass בכלל יש כזו פונקציה? הרי List היא מחלקה גנרית שלא "יודעת" על איזו מחלקה היא עובדת - מי שכתב את הפונקציה Sort לא הכיר את המחלקה MyClass כשהוא כתב אותה. אז לשמחתנו, קיים ממשק בשם IComparable שמגדיר את הפונקציה CompareTo. לכן כל מה שצריך לעשות הוא ש-MyClass תממש את IComparable ותגדיר את הפונקציה CompareTo. הפונקציה List.Sort יכולה לבדוק ש-MyClass מממשת את IComparable, ואז (ע"י casting) להפעיל את הפונקציה CompareTo בשביל לבצע את ההשוואה.

קישור לתוכן
שתף באתרים אחרים

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

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

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

קישור לתוכן
שתף באתרים אחרים

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

קישור לתוכן
שתף באתרים אחרים

מחלקה לא יורשת מממשק, היא מממשת אותו. בג'אווה זה אפילו יותר ברור - בשביל ירושה משתמשים במילה extends ובשביל מימוש של ממשק משתמשים במילה implements (כלומר אם לדוגמה A היא מחלקה שיורשת מ-B ומממשת את C ו-D אז כותבים class A extends B implements C,D).

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

קישור לתוכן
שתף באתרים אחרים

ממשק הוא כמו חוזה.

ההבדל בין לממש interface לבין לרשת ממחלקה הוא:

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

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

דוגמה.

נניח יש ספרייה שכתבתי שנותנת לך לצייר צורות תלת מימדיות על המסך. יש לה ממשקים: cube, piramyde, box, ball ועוד צורות.

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

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

אז יבוא מפתח ויממש את המחלקות האלה וכולם יוכלו להשתמש בהם.

יכול לבוא מפתח אחר שחושב שהוא יכול לממש את ball בצורה טובה ויעילה יותר. מעולה, לא?

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

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

בנוסף, מתודות שמורות (protected) שהשתמשתי בהם יעברו הלאה. גם שדות שכתבתי יעברו בירושה, אולי זה מיותר לגמרי ומבזבז זיכרון?

קישור לתוכן
שתף באתרים אחרים

הוא אמור ליצור ממשק משותף למחלקות מסוגים שונים לחלוטין

סורי שאני לא הכי מבין את זה , מה זאת אומרת ליצור ממשק משותף...

נכון שאני יכול ליצור ממשק בעל 3 חתימות למשל x y z ולממש אותן במחלקות שונות, אבל אז במה הוא בדיוק שונה מהורשה רגילה...

חוץ מהעובדה שאני יכול לקשור מחלקה ליותר ממשק אחד

קישור לתוכן
שתף באתרים אחרים

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

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

קישור לתוכן
שתף באתרים אחרים

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

אשמח לדוגמא בו תתנו לי דוגמא לממשק שהייתם מיישמים אותו במחלקות שונות אחת מהשניה..

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

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

1. כמו שכתבתי אחידות ונוחות בקוד.

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

קישור לתוכן
שתף באתרים אחרים

נראה לי ש-#C, לא שזה משנה. הרעיון הוא אותו רעיון.

ממשק זה הדרך של המחלקה שלך לומר "אני יודעת לעשות x,y,z". זה מאפשר למחלקות/פונקציות אחרות להשתמש בה בלי לדעת שום דבר על המימוש הפנימי שלה.

לדוגמה: נניח שלמחלקה שלך קוראים MyClass. אתה מחזיק רשימה של איברים מהמחלקה - <List<MyClass. עכשיו, אתה רוצה למיין את הרשימה הזו. איזה יופי - יש ל-List פונקציה בשם Sort! אבל רגע, איך List.Sort יודעת לפי מה למיין את הרשימה? היא צריכה לדעת איך להשוות בין שני אובייקטים מטיפוס MyClass. אז רק צריך ש-MyClass תממש פונקציה בשם CompareTo, שתקבל אובייקט אחר מסוג MyClass ואז תחזיר מי מהם גדול יותר. עכשיו List.Sort יכולה פשוט להשתמש בפונקציה הזו כדי להשוות בין האובייקטים. אבל רגע.... איך היא יודעת של-MyClass בכלל יש כזו פונקציה? הרי List היא מחלקה גנרית שלא "יודעת" על איזו מחלקה היא עובדת - מי שכתב את הפונקציה Sort לא הכיר את המחלקה MyClass כשהוא כתב אותה. אז לשמחתנו, קיים ממשק בשם IComparable שמגדיר את הפונקציה CompareTo. לכן כל מה שצריך לעשות הוא ש-MyClass תממש את IComparable ותגדיר את הפונקציה CompareTo. הפונקציה List.Sort יכולה לבדוק ש-MyClass מממשת את IComparable, ואז (ע"י casting) להפעיל את הפונקציה CompareTo בשביל לבצע את ההשוואה.

ואז (ע"י casting) להפעיל את הפונקציה CompareTo בשביל לבצע את ההשוואה.
אשמח לדוגמא לקוד כזה ...

הבנתי את העניין.... אני פשוט לא יודע מתי אני אגיד לעצמי וואלה פה עדיף שאצור ממשק...

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...