7

תכנות מונחה עצמים - יסודות

OOP Basics

🎯 מטרות הלמידה

  • הבנת מחלקות ואובייקטים
  • יצירת מחלקה עם __init__
  • הבנת self ומתודות
  • Attributes ומשתני מופע

7.1מחלקות ואובייקטים

🏗️ מחלקה = תבנית

מחלקה (Class) היא תבנית ליצירת אובייקטים. כמו 'תוכנית בניה' לבית.

אובייקט (Object) הוא מופע ספציפי של המחלקה. כמו 'הבית עצמו'.

# הגדרת מחלקה
class Dog:
    pass  # מחלקה ריקה

# יצירת אובייקטים
dog1 = Dog()
dog2 = Dog()
print(type(dog1))  # 

7.2__init__ - הבנאי

🔨 בנאי = אתחול אובייקט

__init__ היא מתודה מיוחדת שרצה אוטומטית כשיוצרים אובייקט חדש.

class Person:
    def __init__(self, name, age):
        self.name = name  # משתנה מופע
        self.age = age

# יצירת אובייקט - __init__ רץ אוטומטית!
p1 = Person('דני', 25)
print(p1.name)  # דני
print(p1.age)   # 25

7.3self ומתודות

👆 self = האובייקט עצמו

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

class BankAccount:
    def __init__(self, balance):
        self.balance = balance
    
    def deposit(self, amount):
        self.balance += amount
    
    def withdraw(self, amount):
        if amount <= self.balance:
            self.balance -= amount
            return True
        return False

acc = BankAccount(1000)
acc.deposit(500)   # self = acc
print(acc.balance)  # 1500

7.4הסתרת נתונים ו-Name Mangling

🔒 משתנים פרטיים עם __

בפייתון, הוספת שני קווים תחתונים לפני שם משתנה (__var) הופכת אותו לפרטי (Private). פייתון מבצעת Name Mangling ומשנה את שמו ל-_ClassName__var.

💡 ניסיון לגשת ישירות למשתנה הפרטי מחוץ למחלקה יזרוק AttributeError!
class BankAccount:
    def __init__(self, bal=0):
        self.__balance = bal  # פרטי!

    def deposit(self, amount):
        self.__balance += amount

    def get_balance(self):
        return self.__balance

acc = BankAccount(1000)
acc.deposit(500)
print(acc.get_balance())   # 1500 ✓

# ניסיון גישה ישירה - שגיאה!
# print(acc.__balance)     # AttributeError
# אבל... name mangling אפשרי:
print(acc._BankAccount__balance)  # 1500 (לא מומלץ!)
⚠️ מלכודת מבחן: __ לא מונע גישה לחלוטין — פייתון רק משנה את השם. Name mangling הוא מנגנון הגנה, לא אבטחה מוחלטת.

7.5משתני מחלקה vs משתני מופע

📊 שני סוגי משתנים

משתנה מופע (Instance)משתנה מחלקה (Class)
מוגדר ב-__init__ עם selfמוגדר ישירות תחת המחלקה
ייחודי לכל אובייקטמשותף לכל האובייקטים
גישה: self.varגישה: ClassName.var או self.var
class Student:
    # משתנה מחלקה - משותף לכל!
    student_count = 0

    def __init__(self, name):
        self.name = name          # משתנה מופע - ייחודי
        Student.student_count += 1  # עדכון משתנה מחלקה

s1 = Student('דני')
s2 = Student('מיכל')
s3 = Student('יוסי')

print(s1.name)              # דני
print(Student.student_count)  # 3
print(s1.student_count)     # 3 (גם ככה עובד)
⚠️ מלכודת: אם תגדיר self.student_count = 5 בתוך מתודה, תיצור משתנה מופע חדש שמסתיר את משתנה המחלקה — רק עבור האובייקט הספציפי!

7.6__str__ ו-__repr__

🖨️ ייצוג אובייקט כמחרוזת

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

מתודהמתי נקראתלמי מיועדת
__str__print(obj), str(obj)משתמש קצה — קריא
__repr__repr(obj), תצוגה ברשימותמפתח — מדויק
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f'({self.x}, {self.y})'

    def __repr__(self):
        return f'Point(x={self.x}, y={self.y})'

p = Point(3, 4)
print(p)           # (3, 4)        ← __str__
print(repr(p))     # Point(x=3, y=4) ← __repr__

points = [p, Point(1, 2)]
print(points)  # [Point(x=3, y=4), Point(x=1, y=2)] ← __repr__ ברשימות!
💡 אם הגדרת רק __repr__ ולא __str__, פייתון תשתמש ב-__repr__ בשביל שניהם. ההפך לא נכון!

שאלות תרגול

5 שאלות בנושא זה

התחל תרגול →