کاتلین یاد بگیریم! (قسمت ۲)

سلام و خوش و بش! خوب هفته پیش و در قسمت ۱ کاتلین راجع به یسری موضوعات صحبت کردیم. اگرچه به شدت ضروری نیست خوندنش؛ توصیه میکنم بخونید اون قسمت را چون کمی راجع به ویژگی‌های کاتلین سخن رانده شده :) که دونستنش برای اینکه بدونید با چی سر و کار دارید خوبه. اما یک ایده به ذهنم رسید که البته هنوز کامل بررسیش نکردم که بخوام قولش را بدم ولی به نظرم رسید توی فاصله‌ای که این درس‌ها را میذاریم بد نیست که یکسری مطالب کوتاه از حاشیه این زبان بگم. تلاشم را میکنم اما قول روتین بودنش را نمیدم :) ایندفعه هم داشتم دنبال تصویر زیر میگشتم در مورد «نوع‌های پایه» یا همون «Basic Types» که بحث این قسمت هست که یک مطلب خیلی مرتبط به صحبت‌های دو قسمت قبلمون دیدم در سایت slideshare.net. پیشنهاد میکنم ۸ تا اسلاید اولش را ببینین. و بعد اسلاید ۱۴ را. یک مقایسه خیلی جالبی داره با Java و Scala که بنظرم دیدنیه! اسلاید ۶۸ این نمایش خبر از قابلیت Functional Programming میده که خیلی این روزها مورد توجهه! و اما کاتلین!دزدی از یوتیوب!اولین و شیرین‌ترین نکته در مورد «نوع‌های پایه» کاتلین اینه که همه نوع‌ها، «شی» یا «Object» هستند و در نتیجه امکان فراخوانی یکسری ویژگی یا متد روی همه اون‌ها - به تناسب اینکه چه نوعی هستند - وجود داره.پاورقی: اگر نمیدونید «کلاس و شی» چی هستن - البته بعداً مفصل توضیح میدیم - فعلا اینجوری درکش کنید که «کلاس» یک نقشه کلی هست از هر چیزی؛ «ساختمان»، «انسان»، «اشکال هندسی»، «حیوان»، «ماشین»، «زبان برنامه‌نویسی» و غیره. که هر کدامشون یکسری ویژگی‌ها و مشخصات دارند. با این تعریف، یک «شی» میشه یک نمونه از «کلاس» که ویژگی‌ها و مشخصاتش، معلوم هستن. مثلا وقتی میگیم «گربه همسایه بالایی» در واقع ما یک «شی»، «Object» یا «نمونه» منحصر بفرد از کلاس حیوان - و حتی کلاس گربه - را تعریف کردیم که اشاره به «یک گربه منحصر بفرد» داره که مال همسایه طبقه بالاییه و رنگ و اسم (ویژگی‌ها)و مدل راه رفتن و نحوه میو میو کردنش (توابع و رفتارها) برای ما معلومه. و مجموع ویژگی‌ها و رفتارهاش با هیچ گربه دیگری یکسان نیست.خوب از تعریف کلاس و شی که برگردیم میریم سراغ داده‌های پایه که شامل این‌ها میشن:Numbers (اعداد)Characters (کاراکترها)Boolean(true/false) (درست/غلط یا ۰/۱)Arrays (آرایه ها)Strings (رشته ها)ولی قبلش باید بگیم توی Kotlin چجوری میشه «متغیر» تعریف کرد. چون وقتی شما یک نوع داده‌ای تعریف میکنید اغلب نیاز دارید که اون را جایی در برنامه نگه دارید تا بعداً بهش مراجعه کنید. متغیر دقیقاً به همین معنیه. یک فضا در حافظه برنامه، که میشه داخلش یکسری مقادیر - بخوانید هرچیز قابل ذخیره‌سازی - گذاشت و هر وقت لازم بود مقدار ذخیره شده را با صدا کردن اسم اون بخش از حافظه - متغیر - دریافت کرد. دلیل دیگه‌ای که بهش میگیم متغیر اینه که مقدارش میتونه در طول برنامه با رعایت یکسری نکات تغییر کنه.پیش‌نیاز: از اینجا به بعد باید دست به کد بشیم و برای اینکه کد بزنیم چند تا راه هست. یکیش اینه که اگر Android Studio را گرفتید، پلاگین Kotlin را براش فعال کنید. توی اینترنت هست که چجوری اینکار را انجام بدیم مثلاً اینجا. اما به جز این روش میتونید از ویرایشگر آنلاین یا نسخه رایگان IntelliJ IDEA استفاده کنید. من شخصاً از کار کردن با همون سیستم آنلاین لذت میبرم و اونجا کد میزنم. به توصیه دوستم هم هیچ کدی را اینجا نمیذارم که توی اون سیستم کار نکنه :)متغیرها(Variables)در زبان کاتلین دو تا روش تعریف متغیر داریم. استفاده از «val» برای تعریف ثابت‌ها(constants) و استفاده از «var» برای تعریف متغیرها(variables). برای مشخص کردن نوع متغیر میتونیم نوع را - مثلا Int یا String - بعد از var یا val با استفاده از یک دو نقطه آورد. روش توضیح برنامه‌نویسیش این شکلی میشه:var <variableName>:<Type> = <Value>[ ; ] val <variableName>:<Type> = <Value>[ ; ]و به عنوان مثال کد زیر را در نظر بگیرید:val constantFirstNumber: Int = 123 //تعریف یک ثابت از نوع صحیح و مقداردهی 123 var variableFirstNumber: Int = 123; //تعریف یک متغیر از نوع صحیح و مقداردهی 123به چند تا نکته در کد فوق دقت کنید:حرف اول «نوع» را با حرف بزرگ نوشتیم: Int یا String و ...مقداری که به «val» داده می‌شود در طول برنامه قابل تغییر نیست.قرار دادن « ; » semicolon در انتهای دستورات اختیاری هست.تفاوت بین val و var این هست که اولی «immutable» یا در اصطلاح «غیرقابل تغییر» و دومی var، «قابل تغییر» یا «mutable» است.val dateOfBirth = "29th March, 1709" dateOfBirth = "25th December, 1600" // کد کامپایل نمیشود. غیرقابل تغییر var car = "Toyota Matrix" car = "Mercedes-Maybach" // کد کامپایل میشود. تغییر پذیرنکته بسیار مهم اینه اگر نوع را هم حذف کنید کامپایلر کد شما را کامپایل میکنه. ولی به صورت غیرضمنی(Implicit) نوع را تشخیص میده. یعنی وقتی شما مینویسید var variableFirstNumber = 123کامپایلر خودش تشخیص میده این متغیر از نوع عددی هست و در نتیجه در هیچ جای برنامه نمیتونید دستور زیر را بنویسید:var variableFirstNumber = "Salam"و اگر همچین نسبتی را در کد بیارید کامپایلر بهتون خطای زیر را میده:Type mismatch: inferred type is String but Int was expectedتوصیه میشه که در ابتدای کار متغیرهاتون را «غیرقابل تغییر» با «val» تعریف کنید. اینکار باعث میشه کدتون برای کار در فضای «چندبرنامگی» یا «Multi-threading» آماده باشه. دلیلش هم اینه که وقتی با val تعریف می‌کنید اطمینان دارید که پارامترهای تعریف شده، خارج از کنترل شما تغییر نمیکنن. نکته دیگه ای که باید بدونید اینه که میتونیم متغیرهای غیرقابل تغییر «val‌» را با نوعشان تعریف کنیم -مثال زیر - و بعداً در یک جایی از برنامه فقط یکبار بهش مقدار بدیم.val carName: String // Your other code here... carName = "Toyota Matrix" //کامپایل می شودچند تا نکته را بدونید. اول اینکه اگر نوع را مشخص نکنید خطا بهتون میده. یعنی یا باید مقداردهی اولیه بکنید یا نوعش را مشخص کنید تا بتونید بعداً مقداردهی کنید. همچنین اینجا مثل یکسری دیگه زبان‌ها از جمله Java نیست که بتونیم با «کاما» چند متغیر را مقداردهی اولیه کنیم. یعنی امکانش نیست که مثل خط اول این کد، متغیر تعریف کنید و مقدار بدید و بعد کاما بگذارید و متغیر بعدی را تعریف کنید و مقدار بدید. طبیعتا استفاده از «سمیکالن» این امکان را بهتون میده.val carName = "BMW", streetName = "Oke street" // این کد کامپایل نمیشود // کد زیر به خاطر استفاده از سمیکالن به جای کاما کامپایل میشود val carName = "BMW" ; val streetName = "Oke street" // کد زیر کامپایل میشود val carName = "BMW" val streetName = "Oke street"قواعد نامگذاری هم خیلی شبیه قواعد نامگذاری اکثر زبان‌های برنامه‌نویسی روتین هست. با عدد نمیتونیم نام متغیر شروع کنیم. ولی _ و حروف مجازه.خوب حالا که یاد گرفتیم چجوری متغیر تعریف کنیم میریم سراغ انواع پایه کاتلین :) اعداداعداد در کاتلین با زبان برنامه‌نویسی جاوا در برخی زمینه‌ها مشابهت و در بعضی موارد تفاوت‌هایی دارند. برای مثال هیچ تبدیل غیرصریحی یا ضمنی از اعداد کوچک به اعداد بزرگ وجود نداره و ادبیات کدی هم متفاوته در بعضی موارد. فقط اگر قبلا جاوا کار کردید و الان با ما همراهید توجه داشته باشید که کاراکترها در کاتلین جزو اعداد نیستند.Type | Bit Width | Sample ---------------------------------------------------- Double | 64 bit | val myDouble = 45.8 Float | 32 bit | val myFloat = 34.43F Long | 64 bit | val myLong = 40L Int | 32 bit | val myInt = 55 Short | 16 bit Byte | 8 bit ثابت‌های صحیح یا واقعی(Literal Constants)خوب این ثابت ها که گفتیم منظور نوعی از نمایشه که شما به کامپایلر میفهمونید که دارید به یک نوع صحیح واقعی یا درست اشاره میکنید. برای مثال یک نوع Decimal به صورت 123 نشون داده میشه. ولی اگر بخواید نوع Long را نشون بدید یک L بزرگ آخر عددتون میذارید و میشه 123L. کلا خیلی از روش‌های نمایشی جاوا را در خودش داره.به همین شکل Hexadecimal ها با 0x یا 0Xشروع میشن مثل 0x0F. اعداد باینری با 0b یا 0B مثل 0b001101. توجه داشته باشید فعلا نوع Octal یا همون هشت هشتی پشتیبانی نمیشه.علاوه براین کاتلین از نمایش معمول اعداد اعشاری هم پشتیبانی میکنه.Doubles: 123.5, 123.5e10اعداد اعشاری هم با f کوچیک یا بزرگ مشخص میشن:123.5f 123.5Fاستفاده از underline یا _ هم از نسخه ۱.۱ به کاتلین اضافه شده. این برای خوانا کردن کد هست که خوب کار باحالیه که البته از Java نسخه ۷ به بعد هم بوده. کدهای زیر را ببینید:val oneMillion = 1_000_000 val creditCardNumber = 1234_5678_9012_3456L val socialSecurityNumber = 999_99_9999L val hexBytes = 0xFF_EC_DE_5E val bytes = 0b11010010_01101001_10010100_10010010یک نکته ای بالاتر گفتیم که در Kotlin ما نمیتونیم همینطوری اعداد را به نوع‌های بزرگتر تبدیل کنیم. یعنی برای مثال کد زیر اجرا نمیشه:val myNumber = 400 val myNumberAgain: Long = myNumber // throws Error: Type mismatch برای این نوع تبدیل‌ها کاتلین تعدادی متد داره که برخی از اون‌ها به این شرح هستند:toByte()، toInt()، toLong()، toFloat()، toDouble()، toChar() و toShort()val myInt = 987 val myLong = myInt.toLong()در کد بالا ما یک عدد صحیح را به یک عدد از نوع Long تبدیل کردم. برعکس اینکار هم با استفاده از تابع toInt امکان پذیر هست. فقط باید حواستون به این مطلب باشه که وقتی شما یک عدد Long را به یک عدد Int تبدیل میکنید ۳۲ بیت از اطلاعات از بین خواهد رفت. و این موضوع در مورد تمام تبدیل‌های ازنوع بزرگ به کوچک صادق هست.همینطور میتونیم یک رشته را به عدد صحیح تبدیل کنیم. مثال زیر را ببینید:val stringNumber = "101" val intValue = stringNumber.toInt()و حتی خیلی باحالتر از اون و برای اینکه مطمئن بشیم نوع‌ها «شی» هستند:val intValue = "101".toInt()برنامه نویس خوب بشید*: الان برید شروع کنید یک عالمه عدد را به هم تبدیل کنید. مثلا ببینید اگر روی رشته "abc" تابع تبدیل به عدد صحیح را بزنید چی میشه؟ یا اگر روی یک کاراکتر بزنید چی میشه؟ و برای چاپ دستوراتتون فعلا از دستور زیر استفاده کنید:print(<your variable>)خوب این برای این بخش. برنامه ریزیم اینه که بقیه انواع پایه را سریعتر از هفته ای بگم که خیلی سریعتر از این مبحث رد بشیم. کد بزنید. کدبزنید و کد بزنید :)*من هر از گاهی این را میذارم و یکسری نکاتی که بهم کمک کرده بفهمم یک زبان چیکارا میتونه بکنه و چیکارا نمیتونه بکنه را میگم. طبیعتا انجام اینکارا دلبخواهیه ولی چند بار که انجام بدید میبینید که عمق آگاهیتون به اون زبان افزایش داده میشه.