Skip to content

Commit f3cc449

Browse files
author
Saeid Darvish
committed
l18: continue at Multiple Inheritance
1 parent 55fc4cc commit f3cc449

1 file changed

Lines changed: 173 additions & 0 deletions

File tree

lessons/l18.rst

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,183 @@
245245

246246
این برنامه‌نویس است که تصمیم می‌گیرد یک کلاس چگونه طراحی شود. اینکه کدام متد باید از کدام نوع باشد مسئله‌ای است که برنامه‌نویس باید در زمان طراحی کلاس خود به آن فکر کند و از امکانات زبان برنامه‌نویسی پایتون به درستی در جهت بهتر و راحت‌تر به انجام رساندن مسئله خود بهره بگیرد.
247247

248+
249+
.. tip::
250+
251+
هر شی از یک کلاس علاوه بر اینکه از نوع آن کلاس محسوب می‌شود، از نوع superclass نیز به حساب می‌آید. در واقع یک شی نوع subclass، نوع superclass را نیز به ارث می‌برد::
252+
253+
>>> class SuperClass:
254+
... pass
255+
...
256+
>>> class SubClass(SuperClass):
257+
... pass
258+
...
259+
>>> sub = SubClass()
260+
>>>
261+
>>> isinstance(sub, SubClass)
262+
True
263+
>>> isinstance(sub, SuperClass)
264+
True
265+
266+
248267
وراثت چندگانه (Multiple Inheritance)
249268
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
250269

270+
پایتون جزو معدود زبان‌های برنامه‌نویسی مدرنی است که از وراثت چندگانه پشتیبانی می‌کند، چیزی که در زبانی همچون Java نیز وجود ندارد. در واقع پیاده‌سازی وراثت چندگانه چالش‌هایی به همراه دارد، همانند Diamond Problem که در Java ترجیح داده شده است که از وراثت چندگانه پرهیز کند و نبود آن را با پیاده‌سازی مفهومی همچون Interface پوشش دهد [`ویکی‌پدیا <https://en.wikipedia.org/wiki/Interface_(Java)>`__].
271+
272+
فراموش نکنیم در پیاده‌سازی شی گرایی می‌بایست بنابر نیاز برنامه کدهای خود را به کوچک‌ترین واحدهای ممکن تقسیم کنیم و اینکه یک شی بتواند صفات و رفتارهای چندین کلاس را به همراه خود داشته باشد یک نیاز اساسی در شی گرایی است. این الزام فلسفه سادگی پایتون است که مانع از آن می‌شود تا مفاهیمی موازی درکنار هم ایجاد شوند - همانند Class و Interface - وراثت چندگانه راه حل ساده و منطقی زبان برنامه‌نویسی پایتون برای حل این مشکل است و این امکان را می‌دهد که یک کلاس بتواند بیش از یک superclass داشته باشد:
273+
::
274+
275+
>>> class SuperClassA:
276+
... pass
277+
...
278+
>>> class SuperClassB:
279+
... pass
280+
...
281+
>>> class SuperClassC:
282+
... pass
283+
...
284+
>>> class SubClass(SuperClassA, SuperClassB, SuperClassC):
285+
... pass
286+
...
287+
>>> sub = SubClass()
288+
>>>
289+
>>> isinstance(sub, SubClass)
290+
True
291+
>>> isinstance(sub, SuperClassA)
292+
True
293+
>>> isinstance(sub, SuperClassB)
294+
True
295+
>>> isinstance(sub, SuperClassC)
296+
True
297+
298+
نمونه کد بالا نمایش ساختار وراثت چندگانه در پایتون است که در آن کلاس SubClass به ترتیب از سه کلاس SuperClassA و SuperClassB و SuperClassC ارث‌بری دارد.
299+
300+
اکنون مهم‌ترین چالش چگونگی دسترسی به متدهای هر یک از این superclassها می‌باشد. تاکنون برای دسترسی به متدهای superclass از تابع ``super`` استفاده می‌کردیم ولی حالا که صحبت از چندین superclass است، مثلا مقدارهی متد ``__init__`` توسط این تابع چگونه می‌تواند انجام شود؟ چگونه باید به پایتون بگوییم آرگومان‌هایی را که می‌خواهیم دقیقا به متد خاصی از superclass مورد نظر ارسال کند؟ البته نگران نباشید، پایتون مشکلی نخواهد داشت. در ادامه، حالات مختلف حل این مسئله را بررسی خواهیم کرد.
251301

302+
**شیوه یکم:** خیلی ساده، می‌توانیم اصلا از تابع ``super`` استفاده نکنیم و متدهای هر superclass را مستقیم با نام خودش فراخوانی کنیم که البته در این روش لازم است به ازای تمام پارامترهای متد superclass آرگومان متناظر را ارسال نماییم، از جمله برای ``self``:
303+
304+
305+
.. code-block:: python
306+
:linenos:
307+
308+
class SuperClassA:
309+
def __init__(self, param_0, param_3):
310+
print('Called: SuperClassA.__init__()')
311+
self.param_0 = param_0
312+
self.param_3 = param_3
313+
314+
315+
class SuperClassB:
316+
def __init__(self, param_1):
317+
print('Called: SuperClassB.__init__()')
318+
self.param_1 = param_1
319+
320+
class SuperClassC:
321+
def __init__(self, param_2):
322+
print('Called: SuperClassC.__init__()')
323+
self.param_2 = param_2
324+
325+
326+
class SubClass(SuperClassA, SuperClassB, SuperClassC):
327+
def __init__(self, param_0, param_1, param_2, param_3, param_4):
328+
SuperClassA.__init__(self, param_0, param_3)
329+
SuperClassB.__init__(self, param_1)
330+
SuperClassC.__init__(self, param_2)
331+
self.param_4 = param_4
332+
333+
334+
sub = SubClass(0, 1, 2, 3, 4)
335+
336+
print('param_0: ', sub.param_0)
337+
print('param_1: ', sub.param_1)
338+
print('param_2: ', sub.param_2)
339+
print('param_3: ', sub.param_3)
340+
print('param_4: ', sub.param_4)
341+
342+
::
343+
344+
Called: SuperClassA.__init__()
345+
Called: SuperClassB.__init__()
346+
Called: SuperClassC.__init__()
347+
param_0: 0
348+
param_1: 1
349+
param_2: 2
350+
param_3: 3
351+
param_4: 4
352+
353+
354+
**شیوه دوم:** فراخوانی تابع ``super`` یک سینتکس معادل نیز دارد که می‌توانیم از آن استفاده کنیم.
355+
356+
357+
358+
359+
**شیوه سوم:** رفتار تابع ``super`` را عمیق‌تر بشناسیم و درست از آن بهره بگیریم:
360+
361+
362+
.. code-block:: python
363+
:linenos:
364+
365+
class SuperClassA:
366+
def __init__(self, param_0, param_3, *args):
367+
print('Called: SuperClassA.__init__()')
368+
super().__init__(*args)
369+
self.param_0 = param_0
370+
self.param_3 = param_3
371+
372+
373+
class SuperClassB:
374+
def __init__(self, param_1, *args):
375+
print('Called: SuperClassB.__init__()')
376+
super().__init__(*args)
377+
self.param_1 = param_1
378+
379+
class SuperClassC:
380+
def __init__(self, param_2, *args):
381+
print('Called: SuperClassC.__init__()')
382+
super().__init__(*args)
383+
self.param_2 = param_2
384+
385+
386+
class SubClass(SuperClassA, SuperClassB, SuperClassC):
387+
def __init__(self, param_0, param_1, param_2, param_3, param_4):
388+
super().__init__(param_0, param_3, param_1, param_2)
389+
self.param_4 = param_4
390+
391+
392+
sub = SubClass(0, 1, 2, 3, 4)
393+
394+
.. code-block:: python
395+
:linenos:
396+
397+
class SuperClassA:
398+
def __init__(self, param_0, param_3, **kargs):
399+
print('Called: SuperClassA.__init__()')
400+
super().__init__(**kargs)
401+
self.param_0 = param_0
402+
self.param_3 = param_3
403+
404+
405+
class SuperClassB:
406+
def __init__(self, param_1, **kargs):
407+
print('Called: SuperClassB.__init__()')
408+
super().__init__(**kargs)
409+
self.param_1 = param_1
410+
411+
class SuperClassC:
412+
def __init__(self, param_2, **kargs):
413+
print('Called: SuperClassC.__init__()')
414+
super().__init__(**kargs)
415+
self.param_2 = param_2
416+
417+
418+
class SubClass(SuperClassA, SuperClassB, SuperClassC):
419+
def __init__(self, p0, p1, p2, p3, p4):
420+
super().__init__(param_0=p0, param_3=p3, param_1=p1, param_2=p2)
421+
self.param_4 = p4
422+
423+
424+
sub = SubClass(0, 1, 2, 3, 4)
252425
253426
انجمن (Association)
254427
----------------------------------

0 commit comments

Comments
 (0)