جلسه شماره 87رایگان

Generic Bounding

00:20:23

توضیحات جلسه

🎥 آموزش جاوا – قسمت هشتادم از بوت‌کمپ رایگان جاوا 📚 Generics in Java – Bounding (Upper & Lower Bounds) در پنجمین ویدیو از پلی‌لیست تخصصی Generics در جاوا، می‌ریم سراغ یکی از مفاهیم مهم و کاربردی که در بسیاری از ساختارهای حرفه‌ای جاوا استفاده می‌شه: 🎯 مرزبندی در جنریک‌ها یا همان Bounding. اگر همیشه برات سؤال بوده که: «تفاوت Upper Bound و Lower Bound چیه؟» «چرا گاهی از extends و گاهی از super استفاده می‌کنیم؟» یا «Bounded Type Parameter دقیقاً چه کاربردی داره؟» این جلسه دقیقاً برای تو طراحی شده! در این ویدیو بررسی می‌کنیم: 📘 تعریف Bounding (Definition) در ابتدای ویدیو با مفهوم Bounding آشنا می‌شیم و متوجه می‌شیم چرا جاوا این قابلیت رو در جنریک‌ها ارائه کرده. ❓ چرا به Bounding نیاز داریم؟ (Why do we need bounding?) با یک مثال کاربردی، دلیل استفاده از Bounding و مشکلاتی که بدون آن ایجاد می‌شود را بررسی می‌کنیم. ⬆️ Upper Bound (? extends T) می‌فهمیم Upper Bound دقیقاً چه کاری انجام می‌دهد و چه زمانی باید از آن استفاده کنیم. ⬇️ Lower Bound (? super T) در این بخش یاد می‌گیریم Lower Bound چطور کنترل ورودی‌ها را بهتر می‌کند و در چه مواردی کار ما را ساده‌تر می‌کند. 🔤 Bounded Type Parameter (T extends Number) در این بخش وارد یک سطح حرفه‌ای‌تر می‌شیم و بررسی می‌کنیم چطور می‌تونیم برای پارامترهای جنریک محدودیت نوع تعیین کنیم. 🔁 مرور نهایی (Review) در پایان جلسه یک جمع‌بندی داریم تا مطمئن بشیم تفاوت‌ها، کاربردها و قوانین Bounding کاملاً در ذهن تثبیت شده. لینک داکیومنت تدریس: https://github.com/farzadafi/ProgrammingByFarzadAfi/tree/master/document/generic 💬 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi هر جا سؤالی داشتی، داخل گروه بپرس؛ من و مربی‌های گروه همیشه در دسترسیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش پروژه‌محور برای یادگیری عمیق و ورود به بازار کار

جزوه و مستندات

مفاهیم کلیدی

  • Bounding مرزبندی

فرآیندی در Generics است که به کمک آن می‌توان محدوده تایپ‌های ورودی را کنترل کرد. این کار باعث می‌شود علاوه بر حفظ Type Safety، انعطاف‌پذیری کد نیز افزایش پیدا کند.

  • Upper Bounded Wildcard

با استفاده از عبارت ? extends T تعریف می‌شود. این ساختار یعنی تایپ موردنظر می‌تواند خود کلاس T یا هر کلاسی باشد که از آن ارث‌بری کرده است؛ یعنی Subclasses.

  • Lower Bounded Wildcard

با استفاده از عبارت ? super T تعریف می‌شود. این ساختار یعنی تایپ موردنظر می‌تواند خود کلاس T یا هرکدام از کلاس‌های والد آن، یعنی Superclasses، تا سطح Object باشد.

  • Wildcard

علامت سؤال ? نشان‌دهنده یک تایپ ناشناخته یا Unknown Type است. زمانی که با Bounding ترکیب می‌شود، اجازه می‌دهد این تایپ ناشناخته در یک بازه مشخص از سلسله‌مراتب وراثت محدود شود.

  • Type Parameter Bounding

به معنای اعمال محدودیت روی پارامترهای جنریک در سطح تعریف کلاس یا Class است. برای مثال، می‌توان یک پارامتر جنریک را طوری محدود کرد که فقط انواع عددی را بپذیرد.

موارد مصاحبه ای

  • تفاوت اصلی بین Upper Bound و Lower Bound در بحث Read و Write چیست؟

در Upper Bound، یعنی استفاده از extends، خواندن داده‌ها یا Get بسیار امن است؛ چون مطمئن هستیم خروجی حتماً از نوع کلاس پایه است. اما اضافه کردن داده یا Add محدودیت جدی دارد.

در Lower Bound، یعنی استفاده از super، اضافه کردن داده بسیار راحت و امن است. اما هنگام خواندن، کامپایلر نوع دقیق را نمی‌داند و خروجی را Object در نظر می‌گیرد.

  • چرا در ساختار ? extends T نمی‌توانیم عضو جدیدی به لیست اضافه کنیم؟

چون کامپایلر دقیقاً نمی‌داند لیست از چه زیرمجموعه‌ای از T ساخته شده است. برای مثال، اگر لیستی از Animal داشته باشیم که در واقع لیستی از Cat است، اضافه کردن یک Dog به آن باعث بروز خطا در زمان اجرا می‌شود.

جاوا برای جلوگیری از این ریسک، اجازه Add کردن هیچ مقداری، به‌جز null، را نمی‌دهد.

  • چه زمانی از T extends Number در تعریف یک کلاس استفاده می‌کنیم؟

زمانی که می‌خواهیم پارامتر جنریک کلاس فقط شامل انواع عددی مانند Integer، Double و Long باشد و از ورود تایپ‌های غیرمرتبط مانند String یا کلاس‌های سفارشی دیگر جلوگیری کنیم.

  • خروجی متد get در ساختار Lower Bound چیست و چه چالشی دارد؟

خروجی همیشه از نوع Object است. چالش اصلی این است که برای استفاده از متدهای اختصاصی آن کلاس، باید عملیات Casting را به‌صورت صریح یا Explicit انجام دهیم.

سناریو کاربردی

در ویدیو دو سناریوی مهم بررسی شده است:

۱. مدیریت رفتار حیوانات

فرض کنید کلاسی به نام Animal داریم که متد sound() دارد و کلاس‌های Dog و Cat از آن ارث‌بری کرده‌اند.

اگر بخواهیم متدی بنویسیم که لیستی از حیوانات را بگیرد و صدای آن‌ها را پخش کند، از ? extends Animal استفاده می‌کنیم. این کار به ما اجازه می‌دهد هم لیستی از سگ‌ها و هم لیستی از گربه‌ها را به متد پاس دهیم و با خیال راحت متد sound() را روی تک‌تک آن‌ها اجرا کنیم؛ چون مطمئن هستیم هر چیزی که در لیست قرار دارد، حتماً یک Animal است.

۲. کلاس Person با آیدی جنریک

در طراحی کلاس Person ممکن است بخواهیم نوع ID را منعطف نگه داریم؛ برای مثال، گاهی Integer و گاهی Long باشد.

با استفاده از <T extends Number> در تعریف کلاس، مرزبندی می‌کنیم تا فقط انواع عددی به‌عنوان آیدی پذیرفته شوند. اگر کسی تلاش کند کلاسی مانند Animal را به‌عنوان نوع آیدی پاس دهد، کامپایلر همان لحظه خطا می‌دهد.

بیشتر بدانید

  • نکته در مورد Add

در حالت Upper Bound، تنها مقداری که مجاز به اضافه کردن به لیست هستید، مقدار null است.

  • امنیت در خواندن

استفاده از Upper Bound برای متدهایی که فقط وظیفه پردازش و خواندن اطلاعات از یک ساختار داده را دارند، یعنی حالت ReadOnly، بهترین گزینه است.

  • انعطاف در نوشتن

اگر متدی طراحی می‌کنید که وظیفه آن جمع‌آوری و ذخیره اشیا در یک لیست است، استفاده از Lower Bound انعطاف‌پذیری بسیار خوبی به کد شما می‌دهد.