Menu
Coddy logo textTech

מושג הממשק

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

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

ממשק מגדיר אילו פעולות זמינות בלי לציין HOW הן פועלות. זהו חוזה שאומר: "כל אובייקט שמממש את הממשק הזה חייב לספק את הפונקציות האלה."

typedef void (*LogFunc)(const char* message);

typedef struct {
    LogFunc log;
} ILogger;

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

כל קוד שמקבל ILogger אינו תלוי במקום שאליו נשלחת הודעת היומן. אפשר להדפיס אותה למסוף, לכתוב אותה לקובץ או לשלוח נתונים דרך רשת. הקוד הקורא רק יודע שהוא יכול לקרוא ל־log:

void process(ILogger* logger, const char* msg) {
    logger->log(msg);  // אנחנו לא יודעים איך הוא מבצע רישום ביומן
}

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

challenge icon

אתגר

קל

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

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

  • calculator.h: הגדירו כאן את הממשק. צרו טיפוס של מצביע לפונקציה בשם BinaryOp שמקבל שני פרמטרים מסוג int ומחזיר int. לאחר מכן הגדירו מבנה ICalculator שמכיל רק שני מצביעים לפונקציות: operate (מטיפוס BinaryOp) ו-describe (מצביע לפונקציה שאינה מקבלת פרמטרים ואינה מחזירה ערך). המבנה הזה הוא ממשק בלבד. הוא אינו מכיל נתונים, אלא רק התנהגות.
  • main.c: כללו את קובץ הכותרת וממשו פונקציות קונקרטיות שיכולות למלא את דרישות הממשק:
    • add: מחזירה את הסכום של שני מספרים שלמים
    • multiply: מחזירה את המכפלה של שני מספרים שלמים
    • describe_add: מדפיסה Addition
    • describe_multiply: מדפיסה Multiplication
    לאחר מכן צרו מופע של ICalculator, שייכו לו פונקציות בהתאם לקלט והשתמשו בו כדי לבצע חישוב.

התוכנית תקבל שלושה קלטים: שני מספרים שלמים וקוד פעולה (1 לחיבור, 2 לכפל).

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

פלט לדוגמה כאשר הקלטים הם 5, 3 ו-1:

Addition
8

פלט לדוגמה כאשר הקלטים הם 4, 7 ו-2:

Multiplication
28

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

נסו בעצמכם

#include <stdio.h>
#include "calculator.h"

// TODO: ממשו את הפונקציה add
// מחזירה את הסכום של שני מספרים שלמים


// TODO: ממשו את הפונקציה multiply
// מחזירה את המכפלה של שני מספרים שלמים


// TODO: ממשו את הפונקציה describe_add
// מדפיסה "Addition"


// TODO: ממשו את הפונקציה describe_multiply
// מדפיסה "Multiplication"


int main() {
    int num1, num2, op_code;
    scanf("%d", &num1);
    scanf("%d", &num2);
    scanf("%d", &op_code);
    
    // TODO: צרו מופע של ICalculator
    
    
    // TODO: בהתאם ל-op_code (1 עבור add, 2 עבור multiply),
    // חברו את המחשבון לפונקציות המתאימות
    
    
    // TODO: קראו ל-describe דרך הממשק
    
    
    // TODO: קראו ל-operate דרך הממשק והדפיסו את התוצאה
    
    
    return 0;
}
quiz iconבחנו את עצמכם

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

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

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