این مطلب ترجمهای است از مستندات رسمی سایت کاتلین.
تعریف بسته یا پکیج:
تعریف بسته یا پکیج باید اول فایل باشد:
package my.demo import java.util.*
نیازی نیست که بستهها و فولدرها با هم یکسان باشند. فایل میتواند در هر فولدری در سیستم باشد.
تعریف تابع
تابعی که دو تا Int به عنوان ورودی میگیرد و یک Int برمیگرداند:
fun sum(a: Int, b: Int): Int { return a + b }
تابعی با بدنه توصیفی و نوع بازگشتی ضمنی:
fun sum(a: Int, b: Int) = a + b
توضیح: این تابع ساده شده همان تابع بالایی است. در این شکل دوم، کاتلین از بدنه تابع نوع خروجی را تشخیص میدهد یا اصطلاحا استنتاج میکند.
مثال زیر تابعی است که هیچ مقداری را برنمیگرداند. در Java برای این منظور از void استفاده میکردیم ولی در کاتلین از Unit:
fun printSum(a: Int, b: Int): Unit { println("sum of $a and $b is ${a + b}") }
نوع بازگشتی Unit اختیاری است و میتوانید آن را حذف کنید:
fun printSum(a: Int, b: Int) { println("sum of $a and $b is ${a + b}") }
تعریف متغیرها
متغیر فقط خواندنی که یک بار میتوانید به آن مقدار بدهید:
val a: Int = 1 // immediate assignment val b = 2 // `Int` type is inferred val c: Int // Type required when no initializer is provided c = 3 // deferred assignment
متغیرهای تغییر پذیر (که میتوانید به آنها مقادیر متفاوتی نسبت بدهید):
var x = 5 // `Int` type is inferred x += 1
متغیرهای سطح بالا:
val PI = 3.14 var x = 0 fun incrementX() { x += 1 }
توضیحات در کاتلین
مشابه جاوا و جاوااسکریپت، کاتلین از توضیح یک خطی و چند خطی پشتیبانی میکند:
// This is an end-of-line comment /* This is a block comment on multiple lines. */
استفاده از قالبهای رشتهای
در رشتههای کاتلین، با استفاده از عملگر $ میتواند مقدار متغیرها را نوشت:
var a = 1 // simple name in template: val s1 = "a is $a" a = 2 // arbitrary expression in template: val s2 = "${s1.replace("is", "was")}, but now is $a"
استفاده از عبارتهای شرطی
fun maxOf(a: Int, b: Int): Int { if (a > b) { return a } else { return b } }
استفاده از if به عنوان یک عبارت:
fun maxOf(a: Int, b: Int) = if (a > b) a else b
استفاده از مقادیر null و چک کردن null بودن متغیرها
اگر یک متغیر میتواند مقدار null داشته باشد باید با استفاده از ? صراحتا آن را علامت بزنیم.
در این مثال تابع parseInt میتواند مقدار null برگرداند:
fun parseInt(str: String): Int? { // ... }
حالا اگر از این تابع برای مقداردهی به یک متغیر استفاده کرده باشیم، مقدار متغیر میتواند null باشد و ما باید حتما null بودن آن را چک کنیم:
fun printProduct(arg1: String, arg2: String) { val x = parseInt(arg1) val y = parseInt(arg2) // Using `x * y` yields error because they may hold nulls. if (x != null && y != null) { // x and y are automatically cast to non-nullable after null check println(x * y) } else { println("either '$arg1' or '$arg2' is not a number") } }
که میتوان آن را به شکل زیر هم نوشت:
// ... if (x == null) { println("Wrong number format in arg1: '$arg1'") return } if (y == null) { println("Wrong number format in arg2: '$arg2'") return } // x and y are automatically cast to non-nullable after null check println(x * y)
بررسی نوع متغیرها و تبدیل نوع خودکار
عملگر is بررسی میکند که آیا نوع یک متغیر از نوع مشخص شده است یا نه. اگر نوع یک متغیر ثابت با عملگر is بررسی شه باشد نیازی به تغییر نوع در زمان استفاده ندارد:
fun getStringLength(obj: Any): Int? { if (obj is String) { // `obj` is automatically cast to `String` in this branch return obj.length } // `obj` is still of type `Any` outside of the type-checked branch return null }
یا
fun getStringLength(obj: Any): Int? { if (obj !is String) return null // `obj` is automatically cast to `String` in this branch return obj.length }
و یا حتا
fun getStringLength(obj: Any): Int? { // `obj` is automatically cast to `String` on the right-hand side of `&&` if (obj is String && obj.length > 0) { return obj.length } return null }
استفاده از حلقه for
val items = listOf("apple", "banana", "kiwi") for (item in items) { println(item) }
یا
val items = listOf("apple", "banana", "kiwi") for (index in items.indices) { println("item at $index is ${items[index]}") }
استفاده از حلقه while
val items = listOf("apple", "banana", "kiwi") var index = 0 while (index < items.size) { println("item at $index is ${items[index]}") index++ }
استفاده از عبارت when
کارکرد عبارت when بسیار شبیه switch-case در زبان جاوا است ولی ساختار فوقالعاده سادهتر و کاربردیتری دارد و برخی از محدودیتهای switch-case در جاوا را هم ندارد:
fun describe(obj: Any): String = when (obj) { ۱ -> "One" "Hello" -> "Greeting" is Long -> "Long" !is String -> "Not a string" else -> "Unknown" }
استفاده از بازهها
برای این که ببینیم آیا یک عدد در بازه مورد نظر قرار دارد یا نه از عملگر in استفاده میکنیم:
val x = 10 val y = 9 if (x in 1..y+1) { println("fits in range") }
بررسی این که آیا عدد در خارج از بازه قرار دارد یا نه:
val list = listOf("a", "b", "c") if (-1 !in 0..list.lastIndex) { println("-1 is out of range") } if (list.size !in list.indices) { println("list size is out of valid list indices range too") }
چرخیدن روی یک بازه:
for (x in 1..5) { print(x) }
یا چرخیدن بر روی یک تصاعد:
for (x in 1..10 step 2) { print(x) } for (x in 9 downTo 0 step 3) { print(x) }
در حلقه اول چک میشود که آیا x در بازه ۱ تا ۱۰ قرار دارد یا نه. بعد از هر بار اجرای حلقه، در بازه ۲ گام به جلو میرویم. بنابراین این حلقه تکرار مقادیر فرد بین ۱ تا ۱۰ را چاپ میکند.
در حلقه دوم ما بازه را برعکس میپیماییم. از ۹ شروع میکنیم تا ۰ و هر بار ۳ گام جابجا میشویم. بنابراین حلقه تکرار مقادیر ۹ و ۶ و ۳ و ۰ را چاپ میکند.
استفاده از مجموعهها
چرخیدن روی یک مجموعه:
for (item in items) { println(item) }
بررسی این که آیا مجموعه شامل یه شی خاص میشود یا نه، به کمک عملگر in:
when { "orange" in items -> println("juicy") "apple" in items -> println("apple is fine too") }
استفاده از عبارت لامبدا برای فیلتر و نگاشت کردن مجموعه:
fruits .filter { it.startsWith("a") } .sortedBy { it } .map { it.toUpperCase() } .forEach { println(it) }
مثال بالا کل اعضای مجموعه fruits را فیلتر میکند و آنهایی را جدا میکند که با حرف a شروع میشوند، بعد آنها را مرتب میکند و بعد همه آنها را به حروف بزرگ تبدیل میکند و در انتها همه آنها را چاپ میکند. اگر این کار را میخواستید با جاوا انجام دهید چه کار میکردید؟
ساختن کلاس و اشیا
val rectangle = Rectangle(5.0, 2.0) //no 'new' keyword required val triangle = Triangle(3.0, 4.0, 5.0)
سلام …
تشکر .