شیءگرا (Object-Oriented Programming) به عنوان یکی از رویکردهای مهم در برنامهنویسی شناخته میشود. در شی گرایی به دادهها و عملیاتها به عنوان اشیاء نگریسته میشود. این رویکرد نه تنها به برنامهنویسان امکان میدهد که کدها را به شکل مرتب و ساختارمندی بنویسند بلکه از ویژگیهای شی گرایی نیز بهرهمند میشوند. شی گرایی در پایتون نیز پیاده سازی شده است.
پایتون (Python) به عنوان یکی از زبانهای برنامهنویسی محبوب، قابلیتهایی را برای پیادهسازی برنامهنویسی شیءگرا فراهم کرده است. در این مقاله، ما با مفاهیم برنامهنویسی شیءگرا آشنا میشویم و نحوه استفاده از آن در پایتون را بررسی میکنیم. پیشنهاد میکنیم از دیگر آموزشهای ما نیز دیدن فرمایید:
- لیست و نحوه کار با آن
- دیکشنری در پایتون
- Tuple در پایتون
- if در پایتون
- حلقه for
- حلقه while
- تابع در پایتون
- تبدیل نوع داده
مفاهیم پایه شی گرایی در پایتون
1. شیء (Object)
شیء، مفهوم اصلی در برنامهنویسی شیءگرا است. یک شیء میتواند یک نمونه (instance) از یک کلاس باشد و دارای ویژگیها و عملکردهای خود است. به عنوان مثال، اگر کلاسی به نام vehicle داشته باشیم، هر ماشین خاصی که از این کلاس ایجاد شود، یک شیء از نوع vehicle است.
2. کلاس (Class)
کلاس یک قالب برای ایجاد شیء میباشد. این کلاس تعیینکننده ویژگیها و عملکردهایی است که هر شیء از آن استفاده میکند. به عبارت دیگر، کلاس تعریف میکند که یک شیء از چه نوع دادهها و عملیاتهایی باید پشتیبانی کند. در پایتون، کلاسها با استفاده از کلمه کلیدی class
تعریف میشوند.
3. ویژگیها (Attributes)
ویژگیها (یا متغیرها) دادههایی هستند که به هر شیء تعلق دارند و وضعیت آن را مشخص میکنند. این ویژگیها میتوانند از انواع مختلفی مثل عدد صحیح، رشته، یا حتی یک شیء دیگر باشند.
4. متدها (Methods)
متدها عملیاتهایی هستند که بر روی شیء انجام میدهند. آنها به کلاس مربوط به آن شیء مرتبط هستند و میتوانند به ویژگیها دسترسی داشته باشند. به عبارت دیگر، متدها تعیینکننده عملکرد یک شیء هستند.
5. ترکیب (Composition)
ترکیب به معنی ترکیب چندین شیء در یک شیء بزرگتر است. این رویکرد به ما این امکان را میدهد که شیءهای کوچکتر را با هم ترکیب کرده و شیءهای پیچیدهتری بسازیم. این مفهوم به ما این امکان را میدهد که کد را ماژولار و مدیریت کنیم.
6. وراثت (Inheritance)
وراثت به معنی ارثبری ویژگیها و متدهای یک کلاس به کلاسی دیگر است. این ویژگی به ما این امکان را میدهد که یک کلاس جدید را بر مبنای یک کلاس موجود تعریف کرده و ویژگیها و متدهای آن کلاس را به کلاس جدید ارث بری کنیم. این مفهوم به ما امکان مجدداً استفاده از کد و ایجاد ساختارهای سلسلهمراتبی از کلاسها را میدهد.
تعریف کلاس در پایتون
حال که با مفاهیم پایه شی گرایی در پایتون آشنا شدیم، به نگاهی به نحوه تعریف یک کلاس در پایتون میاندازیم. در پایتون، تعریف کلاس با استفاده از کلمه کلیدی class
آغاز میشود. اسم کلاس باید با حرف بزرگ شروع شده و معمولاً با استفاده از نام اصلی کلاس تعیین میشود. به عنوان مثال، فرض کنید کلاسی به نام Person
را تعریف کردهایم:
class Person:
pass
در این تعریف، کلمه class
برای شروع تعریف کلاس استفاده شده است و نام کلاس به عنوان پسوند این تعریف آمده است. دستور pass
به عنوان محتوای این کلاس است.
تعریف ویژگیها و متدها
بعد از تعریف کلاس، میتوانیم ویژگیها و متدهای آن کلاس را تعریف کنیم. ویژگیها، دادههایی هستند که به هر شیء از کلاس تعلق دارند و مقادیر متغیر را تعیین میکنند. متدها عملیاتهایی هستند که بر روی شیء انجام میدهند و عملکرد کلاس را تعیین میکنند.
class Person:
# ویژگیهای کلاس
def __init__(self, name, age):
self.name = name
self.age = age
# متد کلاس
def say_hello(self):
print(f"سلام، من {self.name} هستم و {self.age} سال دارم.")
در این تعریف کلاس Person
، دو ویژگی به نام name
و age
با استفاده از متد __init__
تعریف شدهاند. متد __init__
به عنوان متد سازنده (constructor) شناخته میشود و هنگام ایجاد یک نمونه از کلاس اجرا میشود. متد say_hello
نیز یک متد کلاس است که پیامی را به همراه اطلاعات ویژگیها نمایش میدهد.
ایجاد نمونه از کلاس
پس از تعریف کلاس، میتوانیم نمونهای از آن کلاس را ایجاد کنیم. این نمونه شیءی از کلاس است که میتوانیم با آن کار کنیم. برای ایجاد نمونه از کلاس، از نام کلاس به عنوان یک تابع استفاده میکنیم و پارامترهای مورد نیاز به متد سازنده (constructor) را به عنوان آرگومانها منتقل میکنیم.
# ایجاد نمونه از کلاس
person1 = Person("آرمان", 30)
person2 = Person("سارا", 25)
# فراخوانی متد شیء
person1.say_hello() # خروجی: "سلام، من آرمان هستم و 30 سال دارم."
person2.say_hello() # خروجی: "سلام، من سارا هستم و 25 سال دارم."
در این مثال، دو نمونه از کلاس Person
با نامها و سنهای متفاوت ایجاد شدهاند و سپس متد say_hello
بر روی هر دو نمونه فراخوانی شده است.
وراثت در شی گرایی
یکی از مفاهیم مهم در برنامهنویسی شیءگرا، وراثت (Inheritance) است. این مفهوم به ما این امکان را میدهد که یک کلاس جدید را بر مبنای یک کلاس موجود تعریف کرده و ویژگیها و متدهای آن کلاس را به کلاس جدید ارث بری کنیم.
برای تعریف یک کلاس جدید که از یک کلاس موجود ارث برده، نام کلاس جدید را تعریف کرده و نام کلاس والد (پدر) را به عنوان آرگومان به داخل پرانتز بنویسیم. به عنوان مثال، فرض کنید کلاس Employee
به عنوان کلاس اصلی دارای ویژگیهایی مانند name
و salary
باشد:
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def display_info(self):
print(f"نام: {self.name}, حقوق: {self.salary}")
حالا میخواهیم یک کلاس به نام Manager
تعریف کنیم که از کلاس Employee
ارث برده و ویژگیها و متدهای آن کلاس را بهرهبرداری کند:
# ارث بری از کلاس Employee
class Manager(Employee):
def __init__(self, name, salary, department):
# فراخوانی متد سازنده کلاس مادر
super().__init__(name, salary)
self.department = department
def display_info(self):
print(f"نام: {self.name}, حقوق: {self.salary}, بخش: {self.department}")
در این مثال، کلاس Manager
از کلاس Employee
ارث برده و ویژگیها و متدهای مشترک با کلاس والد را دارد. همچنین، متد display_info
را بازنویسی کردهایم تا اطلاعات بیشتری را نمایش دهد.
تعیین وراثت و چندریختی (polymorphism)
وراثت یکی از مفاهیم مهم شی گرایی در پایتون است که به ما امکان مجدداً استفاده از کد و ایجاد ساختارهای سلسلهمراتبی از کلاسها را میدهد. از طرفی، پلیمورفیسم (Polymorphism) نیز یکی دیگر از مفاهیم اساسی این رویکرد است که به ما امکان انجام عملیاتهای یکسان بر روی اشیاء مختلف را میدهد.
پلیمورفیسم به معنی این است که شیءهای مختلف میتوانند به یک متد یا تابع به شکل متفاوت پاسخ دهند. به عبارت دیگر، اگر چند کلاس از یک متد یا تابع استفاده کنند، هر یک میتوانند عملیات مختلفی انجام دهند. این امکان به ما اجازه میدهد که با استفاده از کد یکسان عملیاتهای مختلفی را انجام دهیم.
برای مثال، در پایتون، میتوانیم از پلیمورفیسم بهرهبرداری کنیم و یک تابع را بر روی اشیاء مختلف اجرا کنیم. به عنوان مثال، فرض کنید دو کلاس به نام Circle
و Rectangle
داشته باشیم، هر یک با متدهای مخصوص به خود:
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
حالا میتوانیم یک تابع به نام calculate_area
تعریف کنیم که بر روی اشیاء این دو کلاس عملیات محاسبه مساحت را انجام دهد:
def calculate_area(shape):
return shape.area()
# ایجاد شیء از کلاس Circle
circle = Circle(5)
# ایجاد شیء از کلاس Rectangle
rectangle = Rectangle(4, 6)
# فراخوانی تابع calculate_area بر روی اشیاء
print("مساحت دایره:", calculate_area(circle)) # خروجی: "مساحت دایره: 78.5"
print("مساحت مستطیل:", calculate_area(rectangle)) # خروجی: "مساحت مستطیل: 24"
در این مثال، تابع calculate_area
به عنوان ورودی یک شیء از یک کلاس میپذیرد و متد area
آن شیء را فراخوانی میکند تا مساحت آن را محاسبه کند. به این ترتیب، میتوانیم همان تابع را بر روی اشیاء مختلف اعمال کنیم و مساحت را محاسبه کنیم.