داستان Null در دارت(نال فرزند سر راهی)
توی قسمت های قبلی دیدیم که Null که یه فرزند ناخلف برای کلاس های Dart بود دردسر های زیادی رو براشون درست میکرد. از یه طرف میگفت من فرزند همه شما ها هستم و یه نمونه از کلاس من (null) میتونه به یه variable از type شما ها اختصاص پیدا کنه و از یه طرف دیگه هیچ کدوم از متد های شما رو پشتیبانی نمیکنم و باعث یه سری از خطاهای ناجور و run time میشم.(میتونی از اینجا داستان قسمت های قبلی رو دنبال کنی)
سرانجام کلاس های Dart یه جلسه بین خودشون تشکیل دادن و نتیجه این جلسه مهم که ساعت ها به طول انجامید این شد که دیگه Null رو به عنوان فرزند قبول نداشته باشن و تصمیم گرفتن خیلی بی سر و صدا اون رو بذارنش سر راه.
و این شد که شکل و شمایل Dart به صورت بالا دراومد.همه کلاس ها مثل روال سابق از Object ارث بری میکردن ولی دیگه Null اون پایین نبود.
حالا با این شرایط وقتی که یه variable ای با یه type ای تعریف میکردیم دیگه نمیتونستیم بهش مقدار null رو بدیم چون که دیگه کلاس Null فرزند کلاس های دیگه نبود.
مثلن کد ساده زیر رو ببینید:
میبینید که اومدم و به یه variable که از نوع String هست مقدار null رو دادم ولی زیرش خط قرمز کشیده و خطا داده و خطا هم به صورت زیر هست :
خطا رو بخونید....
گفته که نمیتونی یه مقدار از نوع Null(حرف بزرگ / کلاس Null) رو بدی به یه variable از نوع String.
خب اینجا یه اتفاق خوب افتاد و دیگه امکان دادن مقدار null به variable ها نیست و اگه چنین کاری رو انجام بدیم همون موقع کد نویسی بهمون خطا میده و نمیذاره کار به موقع اجرا بکشه.
ولی باز هم سر و صدای برنامه نویس ها دراومد.برنامه نویس ها میگفتن که آقااااا ما نمیخوایم که کلن یه کاری کنی که ما نتونیم از Null استفاده کنیم که.حرفمون این بود که یه کاری کنید که در عین این که یه جاهایی یه variable ای امکان گرفتن null رو داره و به قولی nullable هست ولی روند کد نویسی هوشمندتر بشه و همون موقع کد نویسی بهمون یه سری خطاها و هشدارها رو بده نه اینکه بیای کلن Null رو نابود کنی و بذاریش کنار.
ولی این دفعه دیگه کلاس ها زیر بار نرفتن و گفتن ما دیگه نمیتونیم تغییری توی خودمون بدیم و دستمون برای تغییر بسته هست و برید پیش اقای Dart که مشکل رو براتون حل کنه.
پس این شد که اقای Dart موند و یه بچه بدون سرپرست (Null) و برنامه نویس هایی که هم این بچه رو لازمش داشتن و هم از دستش عاصی بودن.
دیگه این بار خود Dart دست به کار شد و یه سری چیزای جدید اختراع کرد که هم از Null بدون استفاده نمونه و هم برنامه نویس ها راضی باشن...
بریم ببینیم چه اتفاقی افتاد...
گفتیم که با کنار گذاشتن Null حالا دیگه وقتی که یه variable ای تعریف میکردیم دیگه نمیتونستیم بهش مقدار null رو بدیم چون که دیگه کلاس Null فرزند کلاس های دیگه نبود. ولی بعضی از مواقع نیاز داشتیم که یه variable بتونه مقدار null رو هم بگیره. مثلن همون برنامه میزرا قلی رو در نظر بگیرید که یه کاربری داشت با یه سری فیلد ها.
خب توی این برنامه ساده مثلن فیلد id و firstname و lastname هیچ موقع null نمیشن(این رو غضنفر به میرزا قلی گفته و بهش اطمینان داده که من هیچ موقع از سمت سرور برای این فیلد ها null نمیفرستم) ولی فیلد friends ممکنه بعضی مواقع null بشه و بعضی مواقع هم نشه. پس وقتی که میرزا قلی داره کلاس user رو میسازه باید بتونه یه جوری این فیلدها رو تعریف کنه که اون سه تا فیلد اول هیچ اجازه ای برای null شدن نداشته باشن ولی فیلد آخر این اجازه رو داشته باشه.
برای variable هایی که میخوایم هیچ اجازه ای برای null شدن نداشته باشن قضیه ساده هست. مثلن وقتی که میگیم :
String myStr
این variable دیگه نمیتونه مقدار null بگیره.
ولی برای جاهایی که نیاز هست یه variable همزمان بتونه مقدار null رو هم بگیره Dart یه type جدید رو معرفی کرد.
Type? myVariable
دارت گفتش که برای variable هایی که نیاز دارن null رو هم بگیرن بعد از نوع متغیر یه علامت ? بگذارید.
String? myStr
مثلن توی کد بالا با گذاشتن یه علامت ? بعد از String باعث میشیم که variable هم بتونه یه مقدار از جنس String بگیره و هم بتونه یه مقدار از جنس Null بگیره(که همون null هست, تنها نمونه ای که میتونیم از کلاس Null بسازیم.)
ولی ببینیم با اضافه کردن این ? چه اتفاقی داره میوفته...
در واقع با اضافه کردن این علامت ? یه Type جدید تولید میشه. مثلن با یه Type از نوع String داریم که با اضافه کردن ? و تبدیلش به ?String یه Type جدید تولید میشه.این Type جدید به صورت زیر تفسیر میشه :
String? => String | Null
یعنی ?String یه Type جدید هست و variable ای که از این جنس هست میتونه مقادیری از جنس String و یا Null داشته باشه.(علامت | به معنای یا هست.) توی دنیای برنامه نویسی به این نوع type ها میگن Union Types. یعنی Type هایی که به variable اجاره میده همزمان مقادیری از type های مختلف رو بگیره. پس نتیجه میگیریم که ?String هم یک Union Type هست چون که وقتی که یه variable با این نوع تعریف بشه همزمان میتونه مقادیر از جنس String یا مقادیری از جنس Null (null) رو بگیره.
به صورت کلی تر میتونیم بگیم که :
Type? => Type | Null
اگه بخوام با شکل بهتون نشون بدم اینجوری میشه :
میبینید که نوع ?String یه نوع جدید هست و به و صورت String | Null تفسیر میشه.یا به عبارت دیگه نوع جدید ?String دو تا فرزند داره که یکی از فرزند هاش String هست و اون یکی هم Null.پس طبق قواعد شی گرایی وقتی که یه variable از جنس ?String تعریف میکنیم میتونیم بهش مقادیری از جنس فرزند هاش یعنی String و یا Null رو بدیم.
حالا یه چیز بهتون بگم بین خودمون بمونه...
یه برنامه نویس حرفه ای باید ادبیاتش هم حرفه ای باشه یعنی وقتی که حرف میزنه هم مشخص باشه که با بقیه فرق داره وکلن دارن حرفه ای صحبت میکنه.
پس از این به بعد اگه یه variable از جنس ?String تعریف کردید دیگه نگید که من یه variable از جنس String دارم چون که این دیگه یه String نیست باید بگید یه variable از جنس String | Null (استرینگ یا نال) یا به عبارت ساده تر یه variable از جنس nullable String دارم. پس :
String => String (or non nullable String)
String? => nullable String
پس تا اینجا فهمیدیم که توی ورژن جدید Dart ما Non nullable Type ها یا همون Type های معمولی رو داریم و همچنین Nullable Type ها که با اضافه کردن یه ? به Type های معمولی تولید میشن.
توی قسمت بعدی قراره میرزا قلی برای بچهای قل آباد کلاس آنلاین برگزار کنه و بهشون null safety رو یاد بده...
مطلبی دیگر از این انتشارات
داستان Null در دارت(دادگاه رسیدگی به اتهامات دارت-1)
مطلبی دیگر از این انتشارات
Git dependencies in Flutter pubspec
مطلبی دیگر از این انتشارات
داستان Null در دارت(دادگاه رسیدگی به اتهامات دارت-2)