reified در کاتلین چیست؟

در محیط‌های JVM مانند Android، Desktop یا Spring Boot که از Kotlin استفاده می‌کنید، type ها در زمان اجرا پاک می‌شوند که این موضوع قابلیت نوشتن الگوریتم‌های عمومی و خوانا را محدود می‌کند.

با این حال، Kotlin این مشکل را با معرفی کلمه کلیدی reified حل کرده است، که type را در زمان اجرا حفظ می‌کند.

reified چگونه کار می‌کند؟

استفاده از reified محدودیت‌هایی دارد. تابع شما باید inline باشد. inlining چه کاری انجام می‌دهد؟ به زبان ساده، inlining یعنی تمام کدهای یک تابع به جای اینکه جداگانه اجرا شوند، مستقیماً به محل فراخوانی آن تابع منتقل می‌شوند. این کار به بهبود عملکرد و جلوگیری از برخی مشکلات مربوط به type ها کمک می‌کند. برای توضیح مفهوم inlining در کاتلین، بیایید نگاهی به این مثال بزنیم:

وقتی شما تابع printWords را به صورت inline تعریف می‌کنید، به کامپایلر می‌گویید که هر جایی این تابع فراخوانی شد، به جای اجرای جداگانه تابع، کد داخل آن را به محل فراخوانی منتقل کند.

بنابراین، کد شما در زمان کامپایل به این شکل تبدیل می‌شود:

در اینجا، به جای اینکه تابع printWords دو بار جداگانه اجرا شود، کد داخل آن تابع مستقیماً به محل‌های فراخوانی منتقل شده است. بنابراین، مفهوم inlining به این معنی است که کد تابع به محل فراخوانی منتقل می‌شود تا هم عملکرد بهبود یابد و هم محدودیت‌های مربوط به type ها از بین برود.

Reified چیست؟

کلمه کلیدی reified در کاتلین به شما اجازه می‌دهد تا type های جنریک را در زمان اجرا (runtime) حفظ کنید. در حالت عادی، type های جنریک در کاتلین و جاوا در زمان کامپایل پاک می‌شوند (به این فرآیند type erasure می‌گویند)، به این معنی که اطلاعات type ها در زمان اجرا در دسترس نیستند. اما با استفاده از reified می‌توانید این اطلاعات را در زمان اجرا نیز حفظ کنید. برای استفاده از reified، تابع شما باید inline باشد.

مزایای استفاده از reified:

  1. حفظ type ها در زمان اجرا: می‌توانید به نوع جنریک در زمان اجرا دسترسی داشته باشید.
  2. نوشتن کدهای عمومی و قابل استفاده مجدد: می‌توانید توابعی بنویسید که با type های مختلف کار می‌کنند و اطلاعات نوع‌ها در زمان اجرا حفظ می‌شود.
  3. بهبود عملکرد: با inlining، سربار فراخوانی توابع کاهش می‌یابد و کد بهینه‌تری اجرا می‌شود.


مثال : این کد نشان می‌دهد چگونه reified می‌تواند در کاتلین استفاده شود تا نوع‌های جنریک را در زمان اجرا حفظ کند. بیایید به طور جزئی‌تر به هر بخش از کد نگاهی بیندازیم:


کد اصلی

در این بخش، word یک متغیر از نوع String است و در همان محلی که این متغیر تعریف شده است، نوع آن به صورت مستقیم شناخته می‌شود. این بدین معنی است که ما می‌توانیم با استفاده از ::class به نوع این متغیر دسترسی داشته باشیم و simpleName آن را چاپ کنیم که در اینجا "String" خواهد بود.

تابع printType بدون reified

در این تابع، ما یک تابع جنریک printType داریم که بدون استفاده از reified تعریف شده است. در کاتلین، توابع جنریک به صورت پیش‌فرض در زمان اجرا اطلاعات نوع‌شان را از دست می‌دهند (type erasure). بنابراین، این کد به درستی کامپایل نمی‌شود زیرا T::class نمی‌تواند در زمان اجرا دسترسی به اطلاعات نوع T داشته باشد.

تابع printType با reified و inline

در این تابع، ما از reified و inline استفاده کرده‌ایم. با استفاده از reified T، می‌توانیم نوع T را در زمان اجرا حفظ کنیم. با استفاده از inline، کد تابع به محل فراخوانی منتقل می‌شود که این اجازه را به ما می‌دهد که از T::class در تابع استفاده کنیم و اطلاعات نوع T در زمان اجرا دسترسی پیدا کند.

استفاده از تابع printType

در اینجا، ما تابع printType را با استفاده از متغیر word از نوع String فراخوانی می‌کنیم. با استفاده از reified، تابع قادر است نوع T را شناسایی کرده و اسم آن را چاپ کند که در اینجا به عنوان خروجی "String" به دست می‌آید.

به طور کلی، استفاده از reified و inline در کاتلین به شما اجازه می‌دهد تا از نوع‌های جنریک در زمان اجرا استفاده کنید و از مزایایی مانند حفظ نوع‌ها و بهبود عملکرد کد برخوردار شوید، به شرطی که توابع شما inline باشند و از reified استفاده کنید.


در چه مواردی reifiedاستفاده می شود؟

  • توابع جنریک: وقتی که می‌خواهید تابعی را تعریف کنید که بتواند با نوع‌های جنریک مختلف کار کند و نیاز به دسترسی به نوع جنریک در زمان اجرا دارید.
  • مواردی که نیاز به بررسی و یا عملکرد متفاوت بر اساس نوع در زمان اجرا دارند: مثلاً بررسی نوع یک متغیر در زمان اجرا یا انجام عملیات خاص بر اساس نوع.
  • تبدیل داده‌ها به صورت دینامیک در زمان اجرا: برای مثال، تبدیل یک لیست از یک نوع خاص به آرایه‌ای از آن نوع.
  • کار با کتابخانه‌های رفلکشن: برای استفاده از قابلیت‌های رفلکشن بر روی نوع‌های جنریک.

ممنون که تا آخر این پست همراه من بودید ، امیدوارم براتون مفید بوده باشه 🙌🙏✌ (:

بقیه آموزش های من با نام (mister developer) را می توانید در تلگرام و اینستاگرام دنبال کنید!!

کانال تلگرام: mister_developerr

اینستاگرام: mister_developerr

موفق و پیروز باشید