מה זה?

לאורך היחידה תרגלנו כלים קונקרטיים — Properties, ירושה, abstract, Interfaces — בלי לעצור ולתת להם שם משותף. שלושת העקרונות המרכזיים של OOP הם בעצם שמות לדברים שכבר עשינו: הכמסה (Encapsulation) זה ה-private/Properties מהשיעור השני; הפשטה (Abstraction) זה ה-abstract class/Interfaces מהשיעורים הרביעי-חמישי; פולימורפיזם זה ה-virtual/override על List<Shape>. השיעור הזה לא מלמד כלים חדשים — הוא נותן להם שפה משותפת.

מילות מפתח שחשוב לזכור

• Encapsulation (הכמסה) — הסתרת פרטי מימוש פנימיים (שדות private), וחשיפת גישה מבוקרת בלבד (Properties, מתודות public)

• Abstraction (הפשטה) — הצגת “מה” משהו עושה, בלי לחשוף “איך” — abstract class/Interface כ-API בלי פרטי מימוש

• Polymorphism (פולימורפיזם) — אותה קריאה מתנהגת אחרת לפי הטיפוס האמיתי בזמן ריצה

• 3 העקרונות + ירושה — ביחד נקראים לעיתים “עמודי ה-OOP”, אך ירושה היא כלי ליישום שלהם, לא עיקרון בפני עצמו

// Encapsulation — from the lesson on Properties
class BankAccount
{
    private double _balance;                         // hidden
    public double Balance => _balance;                // exposed for reading only
    public void Deposit(double amount) => _balance += amount;   // controlled access only
}
// Abstraction — from the lesson on abstract/Interfaces
abstract class PaymentMethod
{
    public abstract void Pay(double amount);   // "what" — pay; not "how"
}

class CreditCard : PaymentMethod
{
    public override void Pay(double amount) => Console.WriteLine($"Charging card: {amount}");
}
// Polymorphism — from the lesson on virtual/override
List<PaymentMethod> methods = new List<PaymentMethod> { new CreditCard() /*, new PayPal() ... */ };
foreach (var method in methods)
{
    method.Pay(100);   // each payment method "knows" how to pay in its own way
}

הסבר עיקרי

Encapsulation הוא לא רק private — הוא גם חשיפה מכוונת. BankAccount לא רק מסתיר את _balance — הוא בכוונה חושף Deposit/Balance כערוצי הגישה היחידים, כדי לשמור על מצב תקין. הרעיון הוא לא “להסתיר הכל”, אלא לחשוף בדיוק את מה שהקורא צריך, בצורה מבוקרת.

Abstraction עונה על “מה” ולא “איך” — abstract class PaymentMethod עם Pay(amount) אומרת “כל אמצעי תשלום יודע לשלם סכום” — בלי לפרט איך (חיוב כרטיס? בקשת API? המרת מטבע?). קוד שמשתמש ב-PaymentMethod (כמו הלולאה בדוגמה) לא צריך לדעת את הפרטים — זו בדיוק המשמעות של “הפשטה”: התעלמות מכוונת מפרטים לא-רלוונטיים לקורא.

איך שלושתם עובדים יחד — Encapsulation שומר על מצב פנימי תקין בכל מחלקה בנפרד; Abstraction מגדירה “חוזה” משותף (PaymentMethod) בין כמה מימושים שונים; Polymorphism מאפשר לקוד קורא לטפל בכולם דרך אותו חוזה, בלי לדעת איזה מימוש קונקרטי מסתתר מאחוריו. שלושתם ביחד הם מה שהופך מערכת מונחית-עצמים לגמישה ולניתנת-להרחבה בלי לשבור קוד קיים.

יתרונות

הכמסה מונעת מצב פנימי לא-תקין ומאפשרת לשנות מימוש פנימי בלי לשבור קוד קורא; הפשטה מפחיתה עומס קוגניטיבי — הקורא מתמודד עם “מה” ולא עם כל “איך” בו-זמנית; פולימורפיזם מאפשר הוספת התנהגות חדשה (טיפוס יורש נוסף) בלי לגעת בקוד הקורא הקיים כלל.

חסרונות

הפשטה-יתר (יותר מדי שכבות abstract/Interface לדברים פשוטים) מוסיפה עקיפין מיותרים; שילוב לא זהיר של שלושת העקרונות יחד עלול ליצור היררכיות מסובכות מדי לתחזוקה — נושא שיטופל ביסודיות בשיעורי SOLID הבאים.

נקודות חשובות

• Encapsulation = הסתרת מימוש + חשיפה מבוקרת (Properties, private)

• Abstraction = “מה” בלי “איך” (abstract class/Interface כחוזה)

• Polymorphism = קריאה זהה, התנהגות שונה לפי טיפוס בזמן ריצה

• ירושה היא כלי מימוש לשלושתם, לא עיקרון רביעי עצמאי בפני עצמו

טעויות נפוצות

• לחשוב ש-Encapsulation = רק “להוסיף private” בלי לחשוב על מה כן לחשוף ולמה

• לבלבל בין Abstraction (מה) ל-Encapsulation (הסתרה) — הם קשורים אך לא זהים

• לצטט את שלושת העקרונות בראיון עבודה בלי דוגמה קונקרטית — תשובה “יבשה” פחות משכנעת מדוגמה מהקוד עצמו

סיכום

הכמסה, הפשטה ופולימורפיזם הם שמות לדברים שכבר תרגלנו לאורך היחידה: הכמסה = private+Properties ששולטים במצב הפנימי; הפשטה = abstract class/Interface שמגדירים “מה” בלי “איך”; פולימורפיזם = virtual/override שמאפשר לאותה קריאה להתנהג אחרת לפי הטיפוס האמיתי. יחד הם הבסיס שעליו כל שאר הקורס — כולל SOLID ותבניות עיצוב ביחידה הבאה — נבנה.

דוקומנטציה רשמית

Microsoft Learn — Object-oriented programming (C#)


תרגילים

תרגיל 1 — זיהוי עקרונות בקוד קיים

המשימה: קחו את הקוד של Shape/Circle/Rectangle מהשיעורים הקודמים ביחידה, וסמנו בכתב איפה מופיע כל אחד משלושת העקרונות (הכמסה/הפשטה/פולימורפיזם).

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

תרגיל 2 — הוספת מימוש פולימורפי

המשימה: הוסיפו class PayPal : PaymentMethod נוסף לדוגמת PaymentMethod מהשיעור, עם override Pay משלו, והוסיפו אותו ל-List<PaymentMethod> הקיימת.

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


פרויקט מסכם

המשימה: בנו מערכת “התראות” (Notifications) פשוטה שמדגימה את שלושת העקרונות יחד.

דרישות:

  1. הפשטה: abstract class Notification עם abstract void Send(string message)
  2. פולימורפיזם: לפחות שני מימושים — EmailNotification ו-SmsNotification, כל אחד עם override Send משלו, ו-List<Notification> שמריצה Send על כולם דרך foreach אחד
  3. הכמסה: כל מימוש שומר שדה פרטי (private) רלוונטי (למשל כתובת מייל/מספר טלפון), חשוף רק דרך קונסטרוקטור, לא Property פתוח לשינוי חופשי

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

מה בפרק הבא

בפרק הבא — Generics ועקרונות SOLID: איך כותבים קוד גמיש לכל טיפוס עם <T>, וחמשת העקרונות שמנחים תכנון מחלקות ומערכות שקל לתחזק ולהרחיב.