Generic Bounding
📖توضیحات درس
📄جزوه
مفاهیم کلیدی
-
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انعطافپذیری فوقالعادهای به کد شما میدهد.
