عملگرهای کنترلی میتونن برای انتخاب یک مسیر مناسب بین 2 یا چند مسیر استفاده شن. در این مقاله توضیح مختصری راجع به عملگرهای زیر رو بررسی میکنیم:
کاربرد اصلی این عملگر یا همون چک کردن یک شرط:
val num1 = 10 val num2 = 20 if (num1 > num2) { print("num1 > num2) } else if (num1 < num2) { print("num1 < num2") } else { print("num1 == num2") } // Output: num1 < num2
تو کاتلین شرط های یک خطی مشابه ساختاری که تو جاوا بود رو نداریم دیگه
(Java--> condition ? val1:val2)
به جاش میشه به حالت زیر تو کاتلین پیادشون کرد:
val num = 0 val isZero = if (num == 0) true else false
یه خاصیتی که if توی کاتلین داره اینه که میتونه یه مقدار رو برگردونه به عنوان خروجی، در نتیجه میتونیم تو قسمت return توابعمون هم ازش استفاده کنیم:
fun getMinValue(a: Int, b: Int): Int { return if (a <= b) { a } else { b } }
نکته: وقتی داریم اینجوری از if استفاده میکنیم حتما باید خط اخر از هر بلاک if و else مقدار موردنظر به عنوان خروجی تابع باشه.
عملگر when جایگزین عملگر switch case (جاوا) در کاتلین هست. با این تفاوت که خیلی قدرتمندتر از switch case هست. این عملگر هم مثل عملگر if میتونه یه مقدار به عنوان خروجی داشته باشه.
استفاده ساده ی این عملگر که مشابه switch case هست به شکل زیر هست:
val color = "RED" when(color) { "RED" -> print("Color is RED") "GREEN" -> print("Color is GREEN") "BLUE" -> print("Color is BLUE") else -> print("Color is Unknown") } // Output: Color is RED
نقطه ی قدرت عملگر when:
fun getValue(input: Any): String { return when (input) { is String -> "Input is a String" in 'A'..'Z' -> "Input is between A to Z" 0 -> "Input is 0" 1, 2 -> "Input is either 1 or 2" in 3..10 -> "Input is between 3 to 10" !in 11..100 -> "Input is not between 11 to 100" else -> "Inside else case" } }
همونطور که میبینید اگر تو ورودی تابع نوع ورودیمون رو any بگذاریم میتونیم هر نوع ورودی رو بهش پاس بدیم. حالا ورودی و خروجی های مختلف رو چک میکنیم:
getValue("Any String")
: خروجی Input is a String
.getValue('D')
: خروجی input is between A to Z
.getValue(0)
: خروجی Input is 0
.getValue(5)
: خروجی Input is between 3 to 10
.getValue(256)
: خروجی Input is not between 11 to 100
.getValue(55)
: خروجی Inside else case
.نکته: از is و is! برای چک کردن نوع ورودیمون استفاده میکنیم. از in و in! برای چک کردن بازه استفاده میکنیم.
حلقه for برای تکرار یک عملیات به تعداد دفعات مشخص استفاده میشه. برای مشخص کردن بازه ی تکرار عملیات در حلقه ی for چند حالت مختلف داریم :
استفاده از کلمه کلیدی in:
با این روش حلقه به تعداد اعضای لیست موردنظر اجرا میشه و در هر چرخش هم ما به اون ایتم که نوبتش رسیده دسترسی داریم.
val fruits = listOf("Apple", "Banana", "Cherries", "Guava") for (fruit in fruits) { println(fruit) } // Output: Apple, Banana, Cherries, Guava
استفاده از عملگر .. :
با این عملگر میتونیم بازه مشخص کنیم. نکته این عمگر اینه که حد بالا و پایینش رو هم شامل میشه یعنی اگر بگیم از 0 تا 5 هم 0 رو شامل میشه هم 5.
for (number in 0..5) { println(number) } // Output: 0 1 2 3 4 5
استفاده از عملگر ()withIndex :
این تابع در هر چرخش یه ایندکس به هر ایتم میده.
val fruits = listOf("Apple", "Banana", "Cherries", "Guava") for ((index, fruit) in fruits.withIndex()) { println("$index - $fruit") } // Output: 0 - Apple, 1 - Banana, 2 - Cherries, 3 - Guava
استفاده از کلمه کلیدی until:
این عملگر هم مثل .. برای مشخص کردن بازه استفاده میشه با این تفاوت که حد بالا رو شامل نمیشه ینی اگر بگیم از 0 تا 5 فقط 0 رو شامل میشه.
for (number in 0 until 5) { println(number) } // Prints: 0 1 2 3 4
استفاده از کلمه کلیدی dwonTo:
این عملگر هم برای مشخص کردن بازه استفاده میشه اما به صورت معکوس از اخر به اول و مشابه عملگر .. حد بالا و پایین رو شامل میشه.
for (number in 5 downTo 0) { println(number) } // Prints: 5 to 0
استفاده از کلمه کلیدی step:
اگر بخواهیم تو هر گام تغییر شمارندمون بیشتر از 1 واحد باشه از این کلمه میتونیم تو حلقمون استفاده کنیم.
for (number in 0..10 step 2) { println(number) } // Prints: 0, 2, 4, 6, 8, 10 for (number in 10 downTo 0 step 2) { println(number) } // Prints: 10, 8, 6, 4, 2, 0 val fruits = listOf("Apple", "Banana", "Cherries", "Guava") for (index in fruits.indices step 2) { println(fruits[index]) } // Prints: Apple, Cherries
استفاده از کلمه کلیدی indices:
این تابع تعداد گام ها رو براساس تعداد ایتم های لیست در نظر میگره و خب از خصوصیت های list هست.
val fruits = listOf("Apple", "Banana", "Cherries", "Guava") for (index in fruits.indices) { println(fruits[index]) } // Prints: Apple, Banana, Cherries, Guava
حلقه while ابتدا شرطی که براش مشخص شده رو چک میکنه و اگر شرط برقرار بود بدنه حلقه رو اجرا میکنه. یعنی ممکنه در صورت برقرار نبودن شرط اصلا بدنه حلقه اجرا نشه.
var i = 5 while (i > 0) { println(i) i-- } // Ouput: 5 4 3 2 1
حلقه do...while برعکس while اول بدنه رو اجرا میکنه بعد شرط رو چک میکنه به این معنی که در هر صورت حداقل یک بار بدنه حلقمون اجرا میشه.
var i = 5 do { println(i) i-- } while (i > 0) // Ouput: 5 4 3 2 1
این عملگر به طور پیش فرض (بدون برچسب) وظیفه اینو داره که نزدیک ترین حلقه رو بشکونه و از ادامه داده شدنش جلوگیری کنه.
همونطور که تو مثال پایین میبینید break حلقه ی for داخلی رو شکسته.
for (x in 0..2) { for (y in 0..2) { if (y > 0) break println("x:$x - y:$y") } } // Output: x:0 - y:0 x:1 - y:0 x:2 - y:0
حالا اگر بخواهیم با دستور break حلقه ی خارجی رو بشکونیم نیاز داریم که برای حلقه موردنظرمون برچسب بگذاریم و با استفاده از اون به دستور break بگیم که حلقه ای که مد نظرمونه رو بشکونه نه نزدیک ترین حلقه رو.
outer@ for (x in 0..2) { for (y in 0..2) { if (y > 0) break@outer println("x:$x - y:$y") } } // Output: x:0 - y:0
این عملگر گامی که توش هستیم رو دیگه ادامه نمیده و مستقیم میره به گام بعدی. مثلا اگر بخواهیم حلقمون فقط اعداد فرد رو چاپ کنه مثل مثال زیر:
for (i in 0..10) { if (i%2 == 0) continue print("$i ") } // Output: 1 3 5 7 9
برای عملگر continue هم میتونیم از برچسب استفاده کنیم و بهش بگیم که برای شروع دوباره برگرده به کدوم خط.
outer@ for (x in 0..3) { for (y in 0..3) { if (y > 1) continue@outer println("x:$x - y:$y") } }// Ouput: x:0 - y:0 x:0 - y:1 x:1 - y:0 x:1 - y:1 x:2 - y:0 x:2 - y:1 x:3 - y:0 x:3 - y:1
منابع: