سلام و امیدوارم هفته خوبی را سپری کرده باشین. هفته پیش در مورد انواع پایه گفتگو کردیم و طبیعتا اکیداً توصیه میکنیم که بخونید بخش قبل را و بعد بیاید سراغ این قسمتمون.
خوب قبل از اینکه شروع بکنم لازمه یک نکتهای را بگم. من هفته پیش فراموش کردم بگم این هفته که تعطیلات هست نمیتونم بنویسم و طبیعتا وقفه بیشتری خواهیم داشت. ازاینکه این موضوع را فراموش کردم بگم عذرخواهی میکنم :)
و بریم سراغ یکی ازجذابترین موضوعات برنامهنویسی یعنی:
قبل از اینکه بریم سراغ این خطا و توانمندی کاتلین در جلوگیری از بروز آن به نظر بهتره یک صحبتی در مورد خود مفهوم null
بکنیم. برای این مفهوم معانی زیادی هست مثل «تهی»، «بیمقدار» و خیلی تعابیر و معانی دیگه. اما اون معنی که من خیلی دوستش دارم را اولین بار در کتاب «مفاهیم بنیادی پایگاه دادهها» تالیف سید محمد تقی روحانی رانکوهی دیدم. در تعریف این واژه آمده:
«هیچمقدار» یعنی مقدار ناموجود، مقدار ناشناخته، مقدار غیر قابل اعمال، مقدار تعریف نشده. گذشته از جزییات میتوان گفت معادل است با همان مفهوم «داده نهست» و یا به تسامح « اطلاع نهست». *
خوب حالا که یک تعریف کامل برای این مفهوم داریم، میتونیم بریم سراغ اصل ماجرا که قدرت کاتلین در جلوگیری از بروز این خطا هست.
اگر قبلا برنامهنویسی کرده باشین به احتمال بسیار زیادی به این خطا برخورد کردید. این خطا به این موضوع اشار داره که شما قصد داشتید با یک شئ هیچمقدار یک فراخوانی انجام بدید - مثلا یک تابع از اون شئ را صدا کنید. این خطا بسیار رایج هست و لازمه جلوگیری ازش اینه که مطمئن بشید شئهای برنامه شما همیشه مقدار دارند. اما در کاتلین کار ساده شده و عملا کامپایلر کاتلین به شما اجازه استفاده از یک متغیر null
را نمیدهد**:
به عبارت دیگر درزبان کاتلین امکان داشتن متغیری با مقدار نهست وجود ندارد مگر آن که بهصورت صریح در کد مشخص کنید که این متغیر قابلیت گرفتن مقدار null
دارد:
توجه کنید که هرگاه ما ?
را بعد از نام نوع - مثلا String
- قرار دهیم به صورت واضح به کامپایلر میگوییم که مقدار این متغیر میتواند به یک شئ اشاره کرده و یا «نهست»، «هیچمقدار»، null
باشد. در مثال بالا ما این موضوع را برای نوع String
دیدیم ولی به همین شکل برای سایر نوعها نیز امکانپذیر است
خوب تا حالا راجع به اینکه چجوری مقدار null
را داخل یک متغیر قرار بدیم صحبت کردیم ولی الان میخوایم بگیم که چجوری کاتلین از این خطای آزاردهنده جلوگیری میکنه. کد زیر را در نظر بگیرید:
کد بالا کامپایل نمیشه چون ما داریم طول یک متغیر از یک شئ null
را درخواست میکنیم که خوب بیمعنی هست و در زبانهای دیگه به شما خطای NullPointerException
را میدهد. اما اینجا کامپایلر کاتلین اجازه کامپایل این کد را نمیدهد و در نتیجه این کد به مرحله اجرا نخواهد رسید چون ممکن است که متغیر ما مقدار null
داشته باشد. در واقع کاتلین اجازه کامپایل کدی را که احتمال بروز این خطا را بدهد نمیدهد.
برای رفع این مشکل کاتلین اپراتوری با نام اپراتور فراخونی امن .?
معرفی کرده که در مثال زیر کاربرد اون را میبینیم:
در مثال بالا با افزودن «اپراتور فراخوانی امن» یا همان .?
به متغیر پیش از فراخوانی یک ویژگی از آن، ما به طور مشخص به کامپایلر اعلام میکنیم که تنها در صورتی ویژگی length
متغیر را فراخوانی کند که متغیر نهست یا null
نباشد. در صورتی که متغیر null
باشد، کامپایلر کاتلین رشته "null"
را به عنوان «نتیجه» عبارت v?.length
در نظر گرفته و آن را چاپ میکند. این موضوع نه تنها برای ویژگیها بلکه برای متدها و توابع شئ نیز صادق است.
توجه داشته باشید که زمانی که تابعی از یک متغیر «هیچمقدارپذیر» را فراخوانی میکنید، مقدار بازگشتی آن نیز «هیچمقدار پذیر» یا nullable
خواهد بود. بنابراین و برای مثال در کد زیر مقدار بازگشتی از عبارت v?.length
زمانی که v
نهست است، ?Int
خواهد بود.
برای رد کردن چک کردن هیچمقدارپذیری میتوانیم به جای .?
از .!!
استفاده کنیم. اگرچه این کار توصیه نمیشود زیرا منجر به بروز خطای NullPointerException
خواهد شد.
:?
این اپراتور که همنام اون خواننده مشهور هم هست :) برای مقداردهی یک متغیر که مقدار null
دارد مورد استفاده قرار میگیرد. مثال زیر را خیلی خوب این مطلب را نشون میده:
در این مثال کامپایلر وقتی با null
در متغیر username
مواجه میشود به دلیل وجود اپراتور الویس مقدار "No Name"
(مقدار جایگزین) را داخل متغیر name
قرار میدهد. در صورتی که اگر مقدار username
برابر با هیچمقدار نبود، مقدار متغیر name
با متغیر username
یکسان میبود.
این هم از بحث nullable
و خطای NullPointerException
که بسیار مسئله مهمی در برنامه نویسی هست. در قسمت بعدی میریم سراغ حلقهها و کنترل گردش :)
* اکیدا توصیه میکنم مطالعه این کتاب را برای درک صحیح مفاهیم پایگاه دادهای رابطهای.
** به پیشنهاد سجاد :) کدها را داخل gist بردم که استفاده کردن ازشون ساده تر باشه ولی خوب دق میده تا لود کنه!!