ارث بری در پایتون — به زبان ساده
در این مطلب، ارث بری در پایتون به طور کامل مورد بررسی قرار گرفته است و مثالهای متعددی به منظور تسهیل درک مطلب همراه با کدهای پایتون آنها ارائه شدهاند.
ارث بری در پایتون
«ارثبری» (Inheritance)، کاربر را قادر میسازد تا کلاسی را تعریف کند که همه عملکرد خود را از کلاس والد داشته باشد و در عین حال، امکان افزودن موارد بیشتر را نیز فراهم میآورد.
در این مطلب، روش استفاده از ارث بری در پایتون آموزش داده شده است.
ارثبری چیست؟
ارثبری یک ویژگی قدرتمند در «برنامهنویسی شیگرا» (Object Oriented Programming) محسوب میشود. این مفهوم به تعریف یک کلاس جدید با میزان کم یا بدون هر گونه تغییر روی یک کلاس موجود اشاره دارد. کلاس جدید، کلاس مشتق شده (فرزند) نامیده میشود و کلاسی که از آن مشتق میشود را «کلاس مبنا» (Base Class) یا «والد» (parent) مینامند.
نحو دستور ارث بری در پایتون
نحو دستور ارث بری در پایتون به صورت زیر است.
1class BaseClass:
2 Body of base class
3class DerivedClass(BaseClass):
4 Body of derived class
کلاس مشتق شده، ویژگیها را از کلاس والد به ارث میبرد و ویژگیهای جدیدی به آن اضافه میکند. این امر منجر به کاربرد مجدد کد میشود.
مثالی از ارث بری در پایتون
برای نشان دادن کاربرد ارث بری در پایتون در ادامه مثالی ارائه شده است. یک چندضلعی، شکل بستهای با ۳ یا تعداد بیشتری وجه است.
فرض میشود که یک کلاس با عنوان Polygon وجود دارد که به صورت زیر تعریف شده است.
1class Polygon:
2 def __init__(self, no_of_sides):
3 self.n = no_of_sides
4 self.sides = [0 for i in range(no_of_sides)]
5
6 def inputSides(self):
7 self.sides = [float(input("Enter side "+str(i+1)+" : ")) for i in range(self.n)]
8
9 def dispSides(self):
10 for i in range(self.n):
11 print("Side",i+1,"is",self.sides[i])
این کلاس، دارای خصیصههایی برای ذخیرهسازی تعداد اضلاع n و بزرگی (اندازه) هر ضلع به عنوان لیست Sides است. متد ()inputSides بزرگی هر ضلع را دریافت میکند، و به طور مشابه ()dispSides آنها را به درستی نمایش میدهد. مثلث، یک چندضلعی با سه ضلع است. بنابراین، کلاسی با نام Triangle ساخته شده است که از Polygon ارثبری میکند. این امر موجب میشود همه خصیصههای موجود در کلاس Polygon به صورت آماده در Triangle وجود داشته باشند. نیازی به تعریف دوباره این موارد نیست (استفاده مجدد از کد). Triangle به صورت زیر تعریف میشود.
1class Triangle(Polygon):
2 def __init__(self):
3 Polygon.__init__(self,3)
4
5 def findArea(self):
6 a, b, c = self.sides
7 # calculate the semi-perimeter
8 s = (a + b + c) / 2
9 area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
10 print('The area of the triangle is %0.2f' %area)
اگرچه، کلاس Triangle دارای یک متد جدید ()findArea برای پیدا کردن و پرینت ناحیه مثلث است. در ادامه، یک اجرای نمونه آمده است.
>>> t = Triangle() >>> t.inputSides() Enter side 1 : 3 Enter side 2 : 5 Enter side 3 : 4 >>> t.dispSides() Side 1 is 3.0 Side 2 is 5.0 Side 3 is 4.0 >>> t.findArea() The area of the triangle is 6.00
میتوان مشاهده کرد که حتی در صورتی که متدهایی مانند ()inputSides و ()dispSides برای کلاس Triangle تعریف نشوند، ما قادر به استفاده از آنها خواهیم بود. اگر یک خصیصه در کلاس پیدا نشد، جستجو به کلاس پایه ادامه پیدا میکند. اگر کلاس پایه خودش از کلاسهای دیگر مشتق شده باشد، این کار به صورت بازگشتی ادامه پیدا میکند.
Method Overriding در پایتون
در مثال بالا، توجه به این نکته لازم است که متد ()__init__ در هر دو کلاس Triangle و Polygon تعریف شده است. هنگامی که این اتفاق میافتد، متد در کلاس مشتق شده آن را در کلاس مبنا override میکند. شایان ذکر است که ()__init__ در Triangle به مورد مشابه در Polygon اولویت دارد.
به طور کلی، هنگام override کردن متد پایه، تمایل به گسترش تعریف به جای جایگزینی آن وجود دارد. کار مشابهی با فراخوانی متد موجود در کلاس پایه از آنچه در کلاس مشتق شده وجود دارد، انجام میشود (فراخوانی Polygon.__init__ از ()__init__ در Triangle. یک گزینه بهتر این است که از تابع توکار ()super استفاده شود. بنابراین، (super().__init__(3 مساوی با (Polygon.__init__(self,3 است و ترجیح داده میشود. دو تابع توکار ()isinstance و ()issubclass برای بررسی ارثبری مورد استفاده قرار گرفته است. تابع ()isinstance در صورتی که شی یک نمونه از کلاس یا دیگر کلاسهای مشتق شده از آن باشد، مقدار True را باز میگرداند. هر کلاس در پایتون، از کلاس مبنای object مشتق میشود.
>>> isinstance(t,Triangle) True >>> isinstance(t,Polygon) True >>> isinstance(t,int) False >>> isinstance(t,object) True
به طور مشابه، ()issubclass برای بررسی ارثبری کلاس مورد استفاده قرار میگیرد.
>>> issubclass(Polygon,Triangle) False >>> issubclass(Triangle,Polygon) True >>> issubclass(bool,int) True