اینترفیس (interface) | گولنگ به زبان ساده
۲۰ اردیبهشت ۱۴۰۴
با مفهوم اینترفیس آشنا میشیم و یاد میگیریم چطور از اینترفیس در زبان GO استفاده کنیم.
اینترفیس در برنامهنویسی یک قرارداد یا الگوست که مشخص میکند چه متدهایی باید توسط یک نوع (type) پیادهسازی شوند، بدون اینکه جزئیات پیادهسازی را مشخص کند.
اینترفیس در اصل رفتار (behavior) یا قابلیتهایی که یک شی باید داشته باشد را توصیف میکند.
در زبان Go، اینترفیسها نوعی داده (type) هستند که فقط امضای متدها را تعریف میکنند و هیچ پیادهسازی ندارند.
در گولنگ پیاده سازی اینترفیس ها به صورت ضمنی انجام میشود بدین معنی که اگر یک type تمام متدهای تعریف شده در یک interface رو داشته باشه، اون interface رو پیادهسازی کرده است.
در مثال زیر File بهطور خودکار Writer را پیادهسازی کرده است زیرا تمامی متدهای آن را دارد:
Type Assertion یا Interface Assertion
type assertion یا interface assertion مکانیزمی است که به توسعهدهنده امکان میدهد تا از یک مقدار با نوع interface، نوع واقعی (concrete type) آن را استخراج کنند.
سینتکس کلی type assertion به صورت زیر است:
i
یک مقدار از نوعinterface
است.T
نوعی است که انتظار داریم مقدارi
واقعاً از آن نوع باشد.value
متغیری است که مقدار استخراجشده با نوعT
در آن ذخیره میشود.
اگر مقدار i واقعاً از نوع T باشد، عملیات موفقیتآمیز خواهد بود. در غیر این صورت، برنامه دچار panic خواهد شد.
برای جلوگیری از بروز panic و بررسی ایمن نوع مقدار، میتوان از فرم دوم type assertion استفاده کرد:
اگر مقدار
i
از نوعT
باشد، متغیرok
مقدارtrue
خواهد داشت.در غیر این صورت،
ok
برابرfalse
بوده وvalue
مقدار صفر نوعT
را خواهد داشت.
این الگو در Go به عنوان comma-ok idiom شناخته میشود و راهکاری رایج برای انجام type assertion به صورت ایمن است.
حالا بیاید یکسری مثال واقعی رو بررسی کنیم:
همچنین اگر interface سفارشی خودتون رو درست کرده باشید میتونید به مشابه عمل کنید:
در مثال بالا در تابع DescribeShape از type assertion استفاده کردیم.
Type assertion همچنین برای بررسی اینکه آیا یک مقدار، پیادهساز یک اینترفیس خاص است یا خیر نیز کاربرد دارد. در این روش باید نوع متغیر خود را از نوع interface تعریف کنیم یا اینکه با type conversion آن را به نوع interface
تبدیل کنیم و سپس مقدار مورد نظر خودمون رو درون این متغیر قرار دهیم و در نهایت با type assertion بررسی کنیم که آیا این دیتا تایپ اینترفیس مورد نظر ما را پیاده سازی میکند یا نه. به مثال زیر دقت کنید:
استفاده از Type Switch
برای بررسی نوع واقعی یک مقدار که از نوع interface است، علاوه بر type assertion، میتوان از type switch استفاده کرد.
اینترفیس خالی (empty interface)
اینترفیس خالی interface{}
به معنای "هر نوعی" است. چون هیچ متدی ندارد، تمام انواع در Go بهطور پیشفرض آن را پیادهسازی میکنند.
اینترفیس خالی میتواند هر نوع دیتایی را در خود جای دهد به همین دلیل در جایی که نیاز دارید تا هر نوع دیتایی را بتوانید دریافت کنید میتوانید از اینترفیس خالی استفاده کنید.
در گولنگ 1.18
نوع any به زبان اضافه شده و در واقع فقط یک نام مستعار (alias) برای interface{}
است، اما باعث میشود کد خواناتر به نظر برسد.
any مانند یک نام بهتر برای interface{}
است که کد را خوانا تر میکند.
معایب استفاده از اینترفیس خالی
اینترفیس خالی
interface{}
نوعی از نوعزدایی (type erasure) است، یعنی نوع واقعی مخفی میشود و برای استفاده دوباره باید از type assertion یا type switch استفاده کرد.استفاده بیش از حد یا بیدلیل از
interface{}
باعث میشود کد خوانایی و ایمنی نوع خود را از دست بدهد زیرا در هنگام توسعه کد نیاز داریم تا کدهای قدیمی تر چک شود تا مطمئن شویم چه نوع داده ای به اینترفیس پاس داده شده است.
ترکیب اینترفیس ها (interface composition)
در Go، به جای ارثبری (inheritance)، از کامپوزیشن (Composition) برای ساختن ساختارها و اینترفیسهای پیچیدهتر استفاده میشود. بدین صورت میتوان چندین اینترفیس را با هم ترکیب کرد و یک اینترفیس بزرگتر ساخت.
فرض کنید دو اینترفیس مجزا داریم:
حالا میخواهیم اینترفیس جدیدی بسازیم که هم Read
و هم Write
داشته باشد:
در اینجا ReadWriter
یک کامپوزیشن از Reader
و Writer
است. هر تایپی (type) که هم Reader
و هم Writer
رو پیادهسازی کنه، ReadWriter
رو هم پیادهسازی کرده است.
در Go توصیه میشود به جای طراحی اینترفیسهای بزرگ، اینترفیسهای کوچک با یک یا دو متد طراحی شوند و در صورت نیاز با کامپوزیشن آنها را ترکیب کنید. این یکی از اصول معروف Go است:
Design small interfaces. Compose them when needed
قسمت قبل: نوع داده struct | گولنگ به زبان ساده
قسمت بعد: جنریک ها (Generics) | گولنگ به زبان ساده