کاتلین فارسی

فهرست

1 - مقدمه

1.1 ) به دوره خوش آمدید

1.2 ) چرا کاتلین؟

2 - مبانی کاتلین

2.1 ) آشنایی با JVM

2.2 ) نصب کردن ابزارآلات

2.3 ) کاتلین REPL

2.4 ) ساختار یک برنامه کاتلین

2.5 ) کاتلین با IntelliJ IDEA

2.6 ) خلاصه بخش دوم

3 - کد نویسی مقدماتی کاتلین

3.1 ) تعریف متغیر در کاتلین

3.2 ) کار با Type های پایه ای

3.3 ) حلقه ها در کاتلین

3.4 ) عبارت های شرطی در کاتلین

3.5 ) اضافه کردن پگیج ها در کاتلین و خلاصه بخض سوم

4 - توابع

4.1 ) توابع در کاتلین

4.2 ) تابع با پارامترهای پیشفرض و نامیده شده

4.3 ) تابع با پرامترهای نامحدود و خلاصه بخش چهارم

5 - کلاس ها

5.1 ) کلاس ها در کاتلین

5.2 ) توابعِ عضو در کاتلین

5.3 ) visibility modifier ها در کاتلین

5.4 ) کلاس های دیتا در کاتلین

5.5 ) کلاس های enum در کاتلین

5.6 ) Object ها در کاتلین و خلاصه بخش پنج

6 - ارث بری

6.1 ) ارث بری در کاتلین

6.2 ) کارکردن با کلاس های abstract در کاتلین

6.3 ) کلاس های interface در کاتلین

6.4 ) نگاه کوتاه به generic ها و خلاصه بخش شش

7 - کارکردن با Null ها

7.1 ) null safety و خلاصه بخش هفت

8 - نکات اضافه

8.1 ) type casting در کاتلین

8.2 ) چندتایی ها (Tuples)

8.3 ) deconstructing values

8.4 ) کار کردن با exception ها

8.5 ) constant ها

8.6 ) annotation ها در کاتلین و خلاصه بخش هشت

9 - نگاه functionalای

9.1 ) توابع Higher-Order

9.2 ) عبارت های لاندا در کاتلین

9.3 ) closure ها در کاتلین

9.4 ) عبارت های الحاقی در کاتلین و خلاصه بخش نهم

10 - قابلیت همکاری و Interoperability

10.1 ) همکاری با جاوا

10.2 ) صحبت کردن با جاوا از کاتلین

10.3 ) کار کردن با null ها از جاوا

10.4 ) صحبت کردن با کاتلین از جاوا

10.5 ) توابع و خصیصه های درجه اول

10.6 ) توابع الحاقی کاتلین از جاوا

10.7 ) همکاری با جاوا 7 و 8 و خلاصه بخش دهم

11 - کتابخانه استاندارد

11.1 ) کتابخانه استاندارد کاتلین و کارکردن با کالکشن ها در کاتلین

11.2 ) مرور کوتاه بر روی filtering و mapping و flatmapping در کاتلین

عبارت های لاندا در کاتلین

ویرایش

تا الان دیدیم وقتی تابع operation ای که جلسه پیش ساختیم رو میخواستیم استفاده کنیم تابع sum رو با صدا زدن نامش استفاده می کردیم ولی آیا واقعا لازمه که تابع رو حتما بسازیم و بعد نامش رو صدا بزنیم؟ چرا نتونیم تابع رو داخل بدنه تابع دیگه بسازیم؟ اینجاست که ما از عبارت های Lambda استفاده میکنیم.

کد زیر رو نگاه کنین:

fun operation(x: Int, y: Int,op: (Int,Int)->Int): Int {
    return op(x,y)
}

fun sum(x: Int, y: Int) = x + y

fun main(args: Array<String>) {
    
    println(operation(2, 3, ::sum))
    println(operation(2, 3, { x, y -> x + y }))
}

دو عبارت بالا یک عمل رو انجام میدن. اگه دقت کنین ما تایپ x و y رو توی بدنه مشخص نکردیم، درواقع کاتلین خودش متوجه میشه که چون داریم دو عبارت 2 و 3 رو به این تابع میدید پس باید x و y از جنس Int باشن! کاتلین خودش متوجه میشه که چه تایپی رو باید به x و y بده! مثلا اگه همین عبارت رو میخواستیم بنویسیم باید اینجوری مینوشیتم:

fun operation(x: Int, y: Int,op: (Int,Int)->Int): Int {
    return op(x,y)
}

fun sum(x: Int, y: Int) = x + y

fun main(args: Array<String>) {
    
     val LambdaSum: (Int, Int) -> Int = { x, y -> x + y }
     println(operation(2, 3, LambdaSum))

}

و دقت کنین که در اینصورت باید تایپ x و y رو مشخص میکردیم!

خب حالا یک تابع High-Order دیگه بسازیم

fun unaryOperation(x:Int,op: (Int) -> Int){

}

fun main(args: Array<String>) {
    unaryOperation(2, { x -> x * x })
}

توی کاتلین به مانند زبون Groovy ، اگر عبارت Lambda تنها یک پارامتر داشته باشه، لازم نیست که ما دقیق بیان کنیم چی رو داریم صدا میزنیم، کافیه از کلیدواژه “it” استفاده کنیم:

fun unaryOperation(x:Int,op: (Int) -> Int){

}

fun main(args: Array<String>) {
    unaryOperation(2, { it * it })
}

در واقع ما توی کاتلین میتونیم تابع High-Order رو ساده تر و هم به صورت منظم تری بنویسیم. توی کاتلین اگر تابع به عنوان اخرین پارامتر به یک تابع High-Order پاس داده بشه میشه اون رو به صورت دیگه ای هم نوشت. مثلا کد بالا رو میتونیم اینجوری هم بنویسیم:

fun unaryOperation(x:Int,op: (Int) -> Int){

}

fun main(args: Array<String>) {
     unaryOperation(2, { it * it })
     unaryOperation(2) {
          it * it
     }
}

ممکنه شما بگین خب این کجا ممکنه به درد بخوره؟ خب بذارین توی یک مثال بهتون تفاوت و قشنگیه سینتکس کاتلین رو نشون بدم.

بیاین یک کلاس بسازیم به نام Database و اون کلاس هم یک تابع داشته باشه به نام commit ، لازم هم نیست بدنه تابع commit رو هم بنویسیم.

class Database {
    fun commit(){
    }
}

حالا خارج کلاس، تابع دیگه ای بنویسیم به نام transaction که یک Database و یک سری کد رو به عنوان ورودی میگیره:

class Database {
    fun commit(){
    }
}

fun transaction(db: Database, code: () -> Unit ){
    try {
        code()
    } finally {
        db.commit()
    }
}

و تنها کاری که میکنه اینه که code رو روی database اجرا میکنه و در انتها اون دیتابیس رو هم commit میکنه.

حالا کافیه که اینجوری ازش استفاده کنیم:

class Database {
    fun commit(){
    }
}

fun transaction(db: Database, code: () -> Unit ){
    try {
        code()
    } finally {
        db.commit()
    }
}

fun main(args: Array<String>) {
      val db = Database()
      transaction(db){
            //interact with database
      }
}

خیلی قشنگ اومدیم یک متغیر دیتابیس درست کردیم و به تابع transaction دادیم که این تابع میاد اون کد هایی که داخل براکت هامون نوشتیم رو اجرا میکنه و در انتها هم دیتابیس رو commit میکنه.

یکی دیگه از روش های ساختن یک تابع High-Order در کاتلین، استفاده از توابع بی نام است.

fun unaryOperation(x:Int,op: (Int) -> Int){

}
fun main(args: Array<String>) {
      unaryOperation(2, fun(x: Int): Int { return x * x })
}

در واقع همونطور که از نامش مشخصه تابعی رو ساختیم که نام نداره. خب ممکنه بپرسین که کجا ممکنه این بدردمون بخوره ؟ برای شروع باید بگم جایی که لازم نباشه تایپ مقدار بازگشتی رو مشخص کنین و یا جایی که دلتون بخواد چندین نقطه داشته باشین که بر حسب شرایط یک مقدار متفاوت رو برگردونن.