תכנות מונחה עצמים (OOP) הוא סגנון תכנות המאפשר עבודה עם מחלקות (Classes) ו-אובייקטים (Objects) כדי לארגן קוד בצורה יעילה וניתנת לשימוש חוזר.
מושגים מרכזיים:
- מחלקות ואובייקטים:
מחלקה היא תבנית (Template) ליצירת אובייקטים. אובייקט הוא מופע (Instance) של מחלקה. - ירושה (Inheritance):
מאפשרת למחלקה אחת לרשת תכונות (Attributes) ושיטות (Methods) ממחלקה אחרת. - פולימורפיזם (Polymorphism):
מאפשר לפונקציות או שיטות לפעול באופן שונה על סמך סוג האובייקט.
מחלקות ואובייקטים
דוגמת קוד: ניהול עובדים
class Employee:
"""A class to represent an employee."""
def __init__(self, name, position, salary):
self.name = name # Employee's name
self.position = position # Employee's position
self.salary = salary # Employee's salary
def describe(self):
"""Print details about the employee."""
print(f"Name: {self.name}, Position: {self.position}, Salary: ${self.salary}")
def give_raise(self, amount):
"""Increase the employee's salary."""
self.salary += amount
print(f"{self.name} received a raise of ${amount}. New salary is ${self.salary}")
# Creating and using objects
employee1 = Employee("Alice", "Developer", 60000)
employee2 = Employee("Bob", "Designer", 55000)
employee1.describe() # Outputs: Name: Alice, Position: Developer, Salary: $60000
employee2.give_raise(5000) # Outputs: Bob received a raise of $5000. New salary is $60000
הסבר על הקוד
- מחלקה
Employee
:__init__
: קונסטרקטור שמגדיר שם, תפקיד ומשכורת.describe
: שיטה שמדפיסה מידע על העובד.give_raise
: שיטה שמעלה את המשכורת של העובד בסכום נתון.
- יצירת אובייקטים:
employee1
ו-employee2
הם אובייקטים נפרדים של המחלקהEmployee
.- לכל אובייקט נתונים משלו ושיטות שניתן לקרוא להן.
ירושה
דוגמת קוד: מחלקת עובדים ומנהלים
class Employee:
"""A base class to represent an employee."""
def __init__(self, name, position, salary):
self.name = name
self.position = position
self.salary = salary
def describe(self):
"""Print details about the employee."""
print(f"Name: {self.name}, Position: {self.position}, Salary: ${self.salary}")
# Inheriting from Employee
class Manager(Employee):
"""A class to represent a manager."""
def __init__(self, name, position, salary, team_size):
super().__init__(name, position, salary) # Inherit attributes from Employee
self.team_size = team_size # Additional attribute for managers
def describe(self):
"""Print details about the manager."""
super().describe() # Call the describe method from Employee
print(f"Team size: {self.team_size}")
# Creating and using objects
manager = Manager("Charlie", "Team Lead", 80000, 10)
manager.describe()
# Outputs:
# Name: Charlie, Position: Team Lead, Salary: $80000
# Team size: 10
הסבר על הקוד
- מחלקה
Manager
:- יורשת את
Employee
באמצעותclass Manager(Employee)
. - הקונסטרקטור משתמש ב-
super().__init__
כדי להגדיר תכונות מהמחלקהEmployee
. - מוסיפה תכונה חדשה
team_size
.
- יורשת את
- שיטה
describe
:super().describe()
: קוראת לשיטהdescribe
של המחלקה האב כדי להדפיס את פרטי העובד.- מוסיפה פרטים על מספר חברי הצוות.
פולימורפיזם
דוגמת קוד: מערכת שכר
class Employee:
"""A base class to represent an employee."""
def __init__(self, name, salary):
self.name = name
self.salary = salary
def calculate_bonus(self):
"""Base bonus for employees."""
return self.salary * 0.05
class Manager(Employee):
"""A class to represent a manager."""
def calculate_bonus(self):
"""Bonus for managers."""
return self.salary * 0.1
class Intern(Employee):
"""A class to represent an intern."""
def calculate_bonus(self):
"""No bonus for interns."""
return 0
# Using polymorphism
employees = [
Employee("Alice", 60000),
Manager("Bob", 80000),
Intern("Charlie", 20000)
]
for employee in employees:
print(f"{employee.name}'s bonus: ${employee.calculate_bonus()}")
# Outputs:
# Alice's bonus: $3000.0
# Bob's bonus: $8000.0
# Charlie's bonus: $0
הסבר על הקוד
- מחלקות עם שיטות זהות:
Employee
,Manager
, ו-Intern
כולן מכילות את השיטהcalculate_bonus
, אך כל אחת מממשת אותה בצורה שונה.
- פולימורפיזם:
- הלולאה
for employee in employees
מאפשרת לקרוא לשיטהcalculate_bonus
לכל אובייקט, והתוצאה משתנה בהתאם למחלקה של האובייקט.
- הלולאה
תרגילים
תרגיל 1:
צרו מחלקה Product
עם תכונות name
ו-price
, ושיטה שמדפיסה את המוצר.
תרגיל 2:
כתבו מחלקה DiscountedProduct
שיורשת מ-Product
, ומוסיפה תכונה discount
. הוסיפו שיטה שמחשבת את המחיר אחרי הנחה.
תרגיל 3:
צרו מערכת רישום של משתמשים עם מחלקות User
, Admin
ו-Guest
. כל מחלקה תכלול שיטה get_permissions
שתשיב הרשאות שונות.
תרגיל 4:
כתבו מחלקה Shape
עם שיטה area
. צרו מחלקות יורשות Circle
ו-Rectangle
שמחשבות שטח בדרכים שונות.
תרגיל 5:
אתגר: צרו מחלקה Account
עם מחלקות יורשות SavingsAccount
ו-CheckingAccount
, כאשר כל אחת מהן מחשבת ריבית בצורה שונה.
הפרויקט הגדול: משחק הטריוויה
נשתמש ב-OOP כדי לייצג שאלות, שחקנים, ואת ניהול המשחק כולו.
- מחלקה
Question
– ייצוג שאלה. - מחלקה
Player
– ייצוג שחקן עם ניקוד. - מחלקה
QuizGame
– ניהול המשחק.
קובץ question.py
class Question:
"""A class to represent a quiz question."""
def __init__(self, text, answer):
self.text = text
self.answer = answer
def is_correct(self, user_answer):
"""Check if the user's answer is correct."""
return str(user_answer).lower() == str(self.answer).lower()
קובץ player.py
class Player:
"""A class to represent a player."""
def __init__(self, name):
self.name = name
self.score = 0
def add_score(self, points):
"""Add points to the player's score."""
self.score += points
קובץ quiz_game.py
from question import Question
from player import Player
class QuizGame:
"""A class to manage the quiz game."""
def __init__(self, questions):
self.questions = questions # List of Question objects
def start(self, player_name):
"""Start the game for a player."""
player = Player(player_name)
for question in self.questions:
print("\n" + question.text)
user_answer = input("Your answer: ").strip()
if question.is_correct(user_answer):
print("Correct!")
player.add_score(1)
else:
print(f"Wrong! The correct answer was: {question.answer}")
print(f"\n{player.name}, your final score is: {player.score}")
def manage_questions(self):
"""Allow admin to manage questions."""
while True:
action = input("\nDo you want to 'add', 'edit', 'remove', or 'done'? ").lower().strip()
if action == "done":
break
elif action == "add":
new_text = input("Enter the question text: ").strip()
new_answer = input("Enter the correct answer: ").strip()
self.questions.append(Question(new_text, new_answer))
print("Question added!")
elif action == "edit":
question_number = int(input("Enter the question number to edit (1-based index): ")) - 1
if 0 <= question_number < len(self.questions):
new_text = input("Enter the new question text: ").strip()
new_answer = input("Enter the new correct answer: ").strip()
self.questions[question_number].text = new_text
self.questions[question_number].answer = new_answer
print("Question updated!")
else:
print("Invalid question number.")
elif action == "remove":
question_number = int(input("Enter the question number to remove (1-based index): ")) - 1
if 0 <= question_number < len(self.questions):
removed_question = self.questions.pop(question_number)
print(f"Removed question: {removed_question.text}")
else:
print("Invalid question number.")
else:
print("Invalid action. Please choose 'add', 'edit', 'remove', or 'done'.")
קובץ main.py
from question import Question
from quiz_game import QuizGame
def load_questions():
"""Load questions from a file and return a list of Question objects."""
questions = []
try:
with open("questions.txt", "r") as file:
for line in file:
text, answer = line.strip().split("||")
questions.append(Question(text, answer))
except FileNotFoundError:
print("Questions file not found. Starting with no questions.")
return questions
def save_questions(questions):
"""Save questions to a file."""
with open("questions.txt", "w") as file:
for question in questions:
file.write(f"{question.text}||{question.answer}\n")
def main():
"""Main function to run the quiz game."""
questions = load_questions()
quiz = QuizGame(questions)
name = input("Enter your name: ").strip()
if name.lower() == "admin":
print("Welcome, Admin!")
quiz.manage_questions()
save_questions(quiz.questions)
else:
print(f"Welcome, {name}!")
quiz.start(name)
if __name__ == "__main__":
main()
הסבר על הקוד
- פונקציה
manage_questions
במחלקהQuizGame
:- מאפשרת למנהל לבצע את הפעולות הבאות:
- הוספה (
add
): הוספת שאלה חדשה לרשימה. - עריכה (
edit
): שינוי הטקסט או התשובה של שאלה קיימת. - מחיקה (
remove
): הסרת שאלה מהרשימה. - סיום (
done
): יציאה ממסך ניהול השאלות.
- הוספה (
- מאפשרת למנהל לבצע את הפעולות הבאות:
- טעינת ושמירת שאלות:
- פונקציה
load_questions
טוענת שאלות מקובץquestions.txt
וממירה אותן לאובייקטים שלQuestion
. - פונקציה
save_questions
שומרת את רשימת השאלות המעודכנת לקובץ.
- פונקציה
- זרימת התוכנית:
- אם המשתמש הוא מנהל (
admin
), מופעלת פונקצייתmanage_questions
. - לאחר הניהול, השאלות המעודכנות נשמרות לקובץ.
- אם המשתמש הוא שחקן רגיל, המשחק מתחיל עם רשימת השאלות הטעונה.
- אם המשתמש הוא מנהל (
דוגמה להרצה
מנהל נכנס:
Enter your name: admin
Welcome, Admin!
Do you want to 'add', 'edit', 'remove', or 'done'? add
Enter the question text: What is the capital of Japan?
Enter the correct answer: Tokyo
Question added!
Do you want to 'add', 'edit', 'remove', or 'done'? done
שחקן רגיל נכנס:
Enter your name: Alice
Welcome, Alice!
What is the capital of Japan?
Your answer: Tokyo
Correct!