Generic WildCard
📖توضیحات درس
📄جزوه
مفاهیم کلیدی
-
Generic مکانیزمی در زبان جاوا که اجازه میدهد کلاسها، اینترفیسها و متدها با انواع دادههای مختلف (Types) به صورت پارامتریک کار کنند. هدف اصلی آن بررسی نوع داده در زمان کامپایل و جلوگیری از خطاهای زمان اجراست.
-
Invariance یک ویژگی در جنریکهای جاوا که طبق آن، رابطهی ارثبری بین انواع داده (مثلاً
StringفرزندObjectاست) به نسخهی جنریک آنها منتقل نمیشود. به زبان ساده،List<String>فرزندِList<Object>نیست. -
Wildcard (?) یک علامت سوال (
?) که در جنریکها به عنوان یک جایگاه نامشخص (Placeholder) برای انواع داده عمل میکند. زمانی استفاده میشود که نوع دقیق داده برای ما اهمیتی ندارد یا میخواهیم متدی بنویسیم که با هر نوع ورودی کار کند. -
Type Safety اطمینان از اینکه عملیات روی دادهها با نوع صحیح انجام میشود. جنریکها با انتقال بررسیها به زمان کامپایل، امنیت کد را بالا برده و از خطاهایی مانند
ClassCastExceptionجلوگیری میکنند. -
Compile-time vs Runtime Checking قبل از جنریکها، بررسی نوع داده در زمان اجرا (Runtime) انجام میشد که منجر به کرش کردن برنامه میشد. با جنریکها، کامپایلر مثل یک دستیار در زمان کدنویسی خطاها را شناسایی میکند.
موارد مصاحبه ای
-
چرا در جاوا نمیتوان
List<String>را بهList<Object>نسبت داد؟ به دلیل خاصیت Invariance. اگر جاوا این اجازه را میداد، امنیت نوع داده (Type Safety) به خطر میافتاد؛ زیرا میتوانستیم در لیستی که در اصل برایStringساخته شده، یک مقدارDoubleقرار دهیم و این موضوع باعث بروز فاجعه در زمان اجرا میشد. -
تفاوت اصلی Wildcard با استفاده از Type Parameter (مانند
<T>) چیست؟ استفاده از Wildcard سادهتر است و خوانایی کد را بالا میبرد. زمانی که در بدنه متد نیازی به ارجاع به نام نوع داده نداریم و صرفاً میخواهیم یک عملیات عمومی (مثل چاپ کردن) انجام دهیم، Wildcard انتخاب بهتری است. -
محدودیت اصلی استفاده از وایلد کارت علامت سوال (
?) چیست؟ هنگام استفاده ازList<?>ما فقط مجاز به خواندن (Read) از لیست هستیم. به دلیل اینکه کامپایلر نوع دقیق دادههای درون لیست را نمیداند، اجازه اضافه کردن (Write) هیچ مقداری (به جز null) را به ما نمیدهد تا امنیت برنامه حفظ شود.
سناریو کاربردی
فرض کنید میخواهید متدی بنویسید که هر لیستی (شامل اعداد، رشتهها یا اشیاء کاستوم) را دریافت کرده و محتویات آن را چاپ کند.
۱. تلاش اول (اشتباه): اگر ورودی متد را List<Object> تعریف کنید، کامپایلر اجازه نمیدهد یک List<String> یا List<Integer> به آن پاس دهید، چون آنها را سابکلاسِ لیستِ آبجکت نمیداند.
۲. تلاش دوم (درست با Wildcard): اگر ورودی متد را به صورت List<?> تعریف کنید، این متد اصطلاحاً انعطافپذیر (Flexible) میشود. حالا میتوانید هر لیستی با هر نوع دادهای را به آن بدهید. متد به راحتی روی لیست پیمایش کرده و آیتمها را چاپ میکند، اما اجازه ندارد عضو جدیدی به این لیست اضافه کند.
بیشتر بدانید
-
نکته کتابخانهای در کدهای داخلی جاوا، کلاس
Collectionsدر متدهایی مانندcopyوsortبه طور گسترده از وایلد کارتها استفاده کرده است تا انعطافپذیری لازم برای کار با انواع کالکشنها را داشته باشد. -
فلسفه طراحی وایلد کارتها برای حل محدودیتهای ناشی از Invariance معرفی شدند تا همزمان با حفظ امنیت کامل (Type Safety)، امکان نوشتن کدهای چندمنظوره و پویا فراهم شود.
-
نکته فنی فراموش نکنید که علامت سوال (
?) به تنهایی به معنای "هر چیزی" است، اما در جلسات پیشرفتهتر خواهید دید که میتوان آن را با کلمات کلیدیextendsوsuperمحدود کرد (Bounded Wildcards).
