Menu
Coddy logo textTech

ממשקים מפורשים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 28 מתוך 70.

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

במימוש מפורש, מקדימים לשם החבר את שם הממשק ומשמיטים את מציין הגישה:

public interface IAmericanPlug
{
    void Connect();
}

public interface IEuropeanPlug
{
    void Connect();
}

public class UniversalAdapter : IAmericanPlug, IEuropeanPlug
{
    void IAmericanPlug.Connect()
    {
        Console.WriteLine("Connected to 120V");
    }
    
    void IEuropeanPlug.Connect()
    {
        Console.WriteLine("Connected to 220V");
    }
}

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

var adapter = new UniversalAdapter();
// adapter.Connect();  // לא יתקמפל!

IAmericanPlug american = adapter;
american.Connect();  // מחובר ל-120V

IEuropeanPlug european = adapter;
european.Connect();  // מחובר ל-220V

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

challenge icon

אתגר

קל

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

תארגן את הקוד שלך בארבעה קבצים:

  • IDisplayable.cs: הגדר ממשק בשם IDisplayable במרחב השמות Reports. הממשק מייצג תוכן שאפשר להציג על המסך. עליו להצהיר על מתודה Render() שמחזירה מחרוזת.
  • IPrintable.cs: הגדר ממשק בשם IPrintable במרחב השמות Reports. הממשק מייצג תוכן שאפשר לשלוח למדפסת. עליו להצהיר גם על מתודה Render() שמחזירה מחרוזת — שים לב שהדבר יוצר התנגשות בין שמות עם IDisplayable!
  • Report.cs: הגדר מחלקה Report במרחב השמות Reports שמממשת גם את IDisplayable וגם את IPrintable. לדוח צריכה להיות תכונה Title (מחרוזת) ותכונה Content (מחרוזת), עם בנאי שמגדיר את שני הערכים. השתמש במימוש מפורש של ממשק כדי לספק התנהגויות שונות של Render():
    • בעת עיבוד לתצוגה: "[SCREEN] {Title}: {Content}"
    • בעת עיבוד להדפסה: "[PRINT] {Title} | {Content}"
  • Program.cs: בקובץ הראשי, צור Report באמצעות ערכי קלט. מכיוון שאפשר לגשת למימושים מפורשים רק דרך משתני ממשק, שמור את אותו דוח גם במשתנה IDisplayable וגם במשתנה IPrintable, ואז קרא ל-Render() בכל אחד מהם כדי להראות כיצד אותו אובייקט מפיק פלט שונה, בהתאם לממשק שבו משתמשים.

תקבל שני קלטים:

  • כותרת הדוח
  • תוכן הדוח

הדפס את הפלט בפורמט הזה:

Display version:
{Render() via IDisplayable}
Print version:
{Render() via IPrintable}

לדוגמה, אם הקלטים הם Sales Report ו-Q4 revenue increased by 15%, הפלט צריך להיות:

Display version:
[SCREEN] Sales Report: Q4 revenue increased by 15%
Print version:
[PRINT] Sales Report | Q4 revenue increased by 15%

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

נסו בעצמכם

using System;
using Reports;

class Program
{
    public static void Main(string[] args)
    {
        // קרא את הקלט
        string title = Console.ReadLine();
        string content = Console.ReadLine();

        // TODO: צור אובייקט Report עם הכותרת והתוכן

        // TODO: שמור את הדוח במשתנה מסוג IDisplayable

        // TODO: שמור את אותו הדוח במשתנה מסוג IPrintable

        // TODO: הדפס את גרסת התצוגה באמצעות קריאה ל-Render() דרך IDisplayable
        Console.WriteLine("Display version:");
        // הדפס כאן את התוצאה של Render()

        // TODO: הדפס את גרסת ההדפסה באמצעות קריאה ל-Render() דרך IPrintable
        Console.WriteLine("Print version:");
        // הדפס כאן את התוצאה של Render()
    }
}
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C# אונליין