Faragiri

همهٔ زبان‌ها

آموزش اینترفیسبرنامه‌نویسی شی‌گرا

کلاس انتزاعی هنگام ساختن نمونه می‌ایستد و پروتکل هیچ‌وقت. یکی کلاس‌های خودتان را می‌بندد و دیگری کلاسی را که ننوشته‌اید هم می‌پذیرد.

۴بخش
۳دقیقه خواندن
۴عمق

سه چرخ‌دنده

سه چیزی که فقط با هم می‌چرخند

قرارداد بدون پیاده‌سازی هیچ کاری نمی‌کند و پیاده‌سازی بدون مصرف‌کننده هیچ‌وقت آزموده نمی‌شود.

  • قرارداد
  • پیاده‌سازی
  • مصرف‌کننده
  • قراردادمی‌گوید چه متدی لازم است و درباره چگونگی ساکت است
  • پیاده‌سازیهمان متد را می‌نویسد، با ارث بردن یا فقط با داشتن شکل درست
  • مصرف‌کنندهفقط قرارداد را می‌شناسد و به همین دلیل با هر پیاده‌سازی کار می‌کند

این سه چرخ نسبت ثابت دارند: هر قرارداد تازه‌ای که به پایه اضافه شود، همه پیاده‌سازی‌ها را با هم می‌چرخاند و همه‌شان باید به‌روز شوند.

اینترفیس یعنی گفتن اینکه یک شی چه کاری بلد است، بدون گفتن اینکه چطور. پایتون دو راه برایش دارد و تفاوتشان در این است که کِی و بر سر چه چیزی می‌ایستند.

راه اول، کلاس انتزاعی: یک کلاس پایه که از ABC ارث می‌برد و متدش با @abstractmethod علامت خورده. کلاس فرزندی که آن متد را ننوشته باشد اصلا ساخته نمی‌شود:

  • TypeError: Can't instantiate abstract class CsvKhoruji without an implementation for abstract method 'satrha'

این خطا هنگام ساختن نمونه می‌آید و نه هنگام صدا زدن متد، که یعنی خیلی زودتر و در جایی که هنوز معلوم است کدام کلاس ناقص است. بهایش این است که فقط روی کلاس‌هایی کار می‌کند که از همان پایه ارث برده‌اند؛ کلاسی که خودتان ننوشته‌اید هیچ راهی برای برآورده کردنش ندارد.

راه دوم شکل را می‌بیند، نه شجره را

پروتکل قرارداد را با شکل تعریف می‌کند: هر کلاسی که متد لازم را داشته باشد آن را برآورده می‌کند، بی‌آنکه از چیزی ارث ببرد و بی‌آنکه اصلا از وجود پروتکل خبر داشته باشد. با یک پروتکل که متد satrha می‌خواهد، isinstance(Faktor(), DaradSatrha) جواب می‌دهد True و برای کلاسی که آن متد را ندارد False. برای اینکه isinstance اصلا کار کند باید پروتکل با @runtime_checkable علامت بخورد، وگرنه فقط ابزار بررسی نوع آن را می‌بیند و زمان اجرا هیچ خبری از آن نیست.

و اگر هیچ قراردادی ننویسید، چیزی که در زمان اجرا می‌گیرید این است: AttributeError: 'Aks' object has no attribute 'satrha'، در وسط کار و روی داده واقعی. سه سطح هست و نه دو: رد کردن هنگام ساخت، بررسی هنگام تست یا بررسی نوع، و کشف هنگام اجرا. انتخاب میان این سه است و نه میان داشتن و نداشتن اینترفیس.

کدام یک، و بر چه اساسی

اگر همه پیاده‌سازی‌ها را خودتان می‌نویسید و می‌خواهید هیچ‌کدام ناقص نماند، کلاس انتزاعی درست است و سخت‌گیری‌اش همان چیزی است که می‌خواهید. اگر باید کلاسی از یک کتابخانه بیرونی یا یک شی ساختگی در تست را هم بپذیرید، پروتکل تنها گزینه است، چون آن کلاس‌ها هیچ‌وقت از پایه شما ارث نخواهند برد.

نکته‌ای که کمتر گفته می‌شود این است که اینترفیس در جایی معنی دارد که بیش از یک پیاده‌سازی وجود داشته باشد. یک کلاس انتزاعی با یک فرزند، فقط یک لایه اضافه است. رابطه‌اش با ارث‌بری در به اشتراک گذاشتن رفتار، و جایی که تله می‌شود است، و اصلی که همین را با نام می‌گوید در پنج اصل، و اینکه هرکدام جلوی چه چیزی را می‌گیرد است.

جایی که کار گیر می‌کند، جمله «پایتون اینترفیس ندارد» است

در منابع فارسی، اینترفیس تقریبا همیشه به‌عنوان یک مفهوم جاوا معرفی می‌شود و بعد گفته می‌شود پایتون به آن نیازی ندارد چون تایپ اردکی دارد. نتیجه‌اش این است که تیم هیچ قراردادی نمی‌نویسد و متد جاافتاده را روی سرور کشف می‌کند، معمولا در مسیری که کمتر اجرا می‌شود. جمله درست‌تر این است که پایتون کلمه کلیدی اینترفیس ندارد، ولی هر دو شکل الزام را دارد و هر دو در کتابخانه استانداردند. اگر بین این دو مانده‌اید، با پروتکل شروع کنید: نوشتنش ارزان است و هیچ کلاسی را مجبور به ارث بردن نمی‌کند.

ابزار، و سالی که این حرف درست است

در سال ۲۰۲۶ ماژول abc و typing.Protocol هر دو در کتابخانه استاندارد و رایگان‌اند. پروتکل از پایتون 3.8 اضافه شد و جای این را گرفت که برای هر قرارداد یک کلاس پایه بسازید و همه را وادار به ارث بردن کنید. برای اینکه نقض پروتکل پیش از اجرا دیده شود یک بررسی‌کننده نوع لازم است، مثل mypy، که متن‌باز است و پس از نصب به شبکه کاری ندارد؛ بدون آن، پروتکل فقط یک مستند دقیق است.

پرسش بعدی این است که وقتی چند پیاده‌سازی دارید، چه کسی تصمیم می‌گیرد کدام‌یک ساخته شود، که راه‌های ساختن یک شی، وقتی سازنده ساده کافی نیست جوابش را دارد. و اگر پیاده‌سازی‌ها یکدیگر را در بر می‌گیرند به‌جای اینکه جایگزین هم شوند، ترکیب شی‌ها در شکل‌های بزرگ‌تر شکل دیگری است.

کنار این

بالای این