Farzad Afi Logo

FarzadAfi

آموزش تخصصی برنامه نویسی

Generic Bounding

📖توضیحات درس

🎥 آموزش جاوا – قسمت هشتادم از بوت‌کمپ رایگان جاوا 📚 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 هر جا سؤالی داشتی، داخل گروه بپرس؛ من و مربی‌های گروه همیشه در دسترسیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش پروژه‌محور برای یادگیری عمیق و ورود به بازار کار
00:20:23🎯رایگان

📄جزوه

مفاهیم کلیدی

  • 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 انعطاف‌پذیری فوق‌العاده‌ای به کد شما می‌دهد.