الدليل السريع إلى لغة البرمجة Kotlin


issa issa

كوتلن (Kotlin) هي لغة برمجة مخصّصة لمنصّة جافا الافتراضية (Java Virtual Machine أو اختصارًا JVM)، الأندرويد، والمتّصفح. تنتمي للغات statically typed (التي تفحص الأنواع وقت الترجمة). وهي متوافقة مع جافا 100%.

// (//)التعليقات على سطر واحد تبدأ بـ/*
التعليقات المؤلفة من عدة أسطر تبدو كهذه
*/

تعمل الكلمة المفتاحية package بنفس طريقة جافا

package com.learnxinyminutes.kotlin

نقطة الإدخال لبرامج Kotlin هي دالة(تابع) تسمى main ،يمرر التّابع مصفوفة تحتوي على وسطاء arguments لسطر الأوامر.

fun main(args: Array<String>) {

التّصريح عن القيم يتم باستخدام إما var أو val ،تصريح val لا يمكن إعادة تعيينه، في حين يمكن ذلك في var

val fooVal =10

لا يمكننا لاحقًا إعادة تعيين قيمة fooVal لقيمة أخرى.

var fooVar =10
fooVar =20

من الممكن إعادة تعيين قيمة fooVar. في أغلب الحالات، يمكن لكوتلن أن تحدّد ما هو نوع المتغير، لذلك لا داعي لتحديده صراحة في كل مرّة. يمكننا أن نصرّح بنوع المتغير بوضوح كالتالي:

val foo:Int=7

يمكن تمثيل السلاسل بطريقة مماثلة في java. يتم الهروب باستخدام backslash.

val fooString ="My String Is Here!"
val barString ="Printing on a new line?\nNo Problem!"
val bazString ="Do you want to add a tab?\tNo Problem!"
println(fooString)
println(barString)
println(bazString)

تُحدد السلسلة الخام string raw باستخدام triple quote ("""). ويمكن أن تحتوي أسطر جديدة و أية محارف أخرى.

val fooRawString ="""
fun helloWorld(val name :String){
println("Hello, world!")}"""
println(fooRawString)

السلاسل ممكن أن تحتوي تعابير القالب template expressions. تبدأ تعابير القالب بالرمز $.

val fooTemplateString ="$fooString has ${fooString.length} characters"
println(fooTemplateString)// => My String Is Here! has 18 characters

من أجل المتغيرات التي تحوي قيمة فارغة null يجب تحديد ذلك صراحة nullable. يمكن تحديد المتغير قابلاً للقيمة null بإلحاق? بنوعه. ويمكننا الوصول إلى المتحولات القابلة لـ null باستخدام مُعامل التشغيل? ،ويمكننا استخدام عامل التشغيل :? لتحديد قيمة بديلة للاستخدام إذا كان المتغير فارغ null.

var fooNullable:String?="abc"
println(fooNullable?.length)// => 3
println(fooNullable?.length ?:-1)// => 3
fooNullable = null
println(fooNullable?.length)// => null
println(fooNullable?.length ?:-1)// => -1

يمكن التصريح عن الدوال باستخدام الكلمة المفتاحية fun. وتحدد وسطاء الدالة بين قوسين بعد اسم الدالة. ويمكن لوسطاء الدالة اختياريًا الاحتواء على قيمة افتراضية. ويحدّد نوع إرجاع الدالة، إذا لزم الامر بعد المعطيات.

fun hello(name:String="world"):String{return"Hello, $name!"}
println(hello("foo"))// => Hello, foo!
println(hello(name ="bar"))// => Hello, bar!
println(hello())// => Hello, world!

يمكن لبارامتر الدالة أن يوسم بالكلمة المفتاحية vararg للسماح بتمرير عدد متغير من المعطيات إلى الدالة.

fun varargExample(vararg names:Int){
    println("Argument has ${names.size} elements")}
varargExample()// => لا يحوي الوسيط أية عناصر
varargExample(1)// => يحوي الوسيط عنصر واحد
varargExample(1,2,3)// => يحوي  الوسيط 3 عناصر

عندما تتكوّن الدّالة من تعبير واحد فقط، يمكن حذف الأقواس المنحنية { } ويتم تحديد الجسم(العملية) بعد رمز =

fun odd(x:Int):Boolean= x %2==1
println(odd(6))// => false
println(odd(7))// => true

إذا كان نوع الاسترجاع يمكن استنتاجه فلسنا بحاجة لتحديده.

fun even(x:Int)= x %2==0
println(even(6))// => true
println(even(7))// => false

الدوال يمكن أن تأخذ دوال كوسطاء وترجع دالة.

fun not(f:(Int)->Boolean):(Int)->Boolean{return{n ->!f.invoke(n)}}

يمكن للدوال المسمّاة أن تحدّد كوسائط باستخدام معامل التشغيل

val notOdd = not(::odd)
val notEven = not(::even)

يمكن تحديد تعابير Lambda كوسائط

val notZero = not {n -> n ==0}

إذا احتوت lambda على بارامتر واحد فقط يمكن حذف التصريح عنه (جنبًا إلى جنب مع<- )وسيكون اسم البارامتر الوحيد it.

val notPositive = not {it >0}for(i in 0..4){
    println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}")}

تستخدم الكلمة المفتاحية class للتّصريح عن الأصناف.

classExampleClass(val x:Int){
    fun memberFunction(y:Int):Int{return x + y
    }

    infix fun infixMemberFunction(y:Int):Int{return x * y
    }}

لإنشاء حالة instance جديدة نستدعي الباني. ولاحظ أن Kotlin لا تحوي الكلمة المفتاحية new.

val fooExampleClass =ExampleClass(7)

يمكن استدعاء دوال المستخدم باستخدام التنويت النقطي .

println(fooExampleClass.memberFunction(4))// => 11

إذا وُسمت الدالة بالكلمة المفتاحية infix يمكن عندها أن يستدعى باستخدام التنويت الداخلي

println(fooExampleClass infixMemberFunction 4)// => 28

أصناف البيانات Data classes هي طريقة مختصرة لإنشاء الأصناف التي تحتوي بيانات فقط وتنشئ دوال hashCode،equals و toString تلقائيًا.

data classDataClassExample(val x:Int, val y:Int, val z:Int)
val fooData =DataClassExample(1,2,4)
println(fooData)// => DataClassExample(x=1, y=2, z=4)

أصناف البيانات لديها دالة copy

val fooCopy = fooData.copy(y =100)
println(fooCopy)// => DataClassExample(x=1, y=100, z=4)

يمكن أن تفكَك الكائنات Objects في متغيرات متعددة

val (a, b, c)= fooCopy
println("$a $b $c")// => 1 100 4

التفكيك باستخدام حلقة for

for((a, b, c) in listOf(fooData)){
    println("$a $b $c")// => 1 100 4}
val mapData = mapOf("a" to 1,"b" to 2)

Map.Entry قابل للتفكيك كذلك

for((key, value) in mapData){
    println("$key -> $value")}

الدالة with مشابهة لعبارة with في جافا

data classMutableDataClassExample(var x:Int, var y:Int, var z:Int)
val fooMutableData =MutableDataClassExample(7,4,9)
with (fooMutableData){
    x -=2
    y +=2
    z--}
println(fooMutableData)// => MutableDataClassExample(x=5, y=6, z=8)

يمكننا إنشاء قائمة (لائحة) باستخدام الدالة listOf. ستكون القائمة غير قابلة للتغيير ولا يمكن إضافة عناصر أو إزالتها.

val fooList = listOf("a","b","c")
println(fooList.size)// => 3
println(fooList.first())// => a
println(fooList.last())// => c// index يمكن الوصول إلى عناصر القائمة من خلال فهرسها
println(fooList[1])// => b

يمكن إنشاء قائمة قابلة للتعديل باستخدام الدالة mutableListOf

val fooMutableList = mutableListOf("a","b","c")
fooMutableList.add("d")
println(fooMutableList.last())// => d
println(fooMutableList.size)// => 4

يمكن إنشاء تعيين set باستخدام الدّالة setOf

val fooSet = setOf("a","b","c")
println(fooSet.contains("a"))// => true
println(fooSet.contains("z"))// => false

يمكننا إنشاء خريطة map باستخدام الدّالة mapOf

val fooMap = mapOf("a" to 8,"b" to 7,"c" to 9)

يمكن الوصول لقيم الـ Map من خلال مفاتيحها

println(fooMap["a"])// => 8

تُمثل المتتالية Sequences مجموعات تقييمها مؤجل إلى حين الحاجة lazily-evaluated collections. ويمكننا إنشاء متتالية باستخدام الدّالة generateSequence.

val fooSequence = generateSequence(1,{ it +1})
val x = fooSequence.take(10).toList()
println(x)// => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

مثال لاستخدام متتالية لتوليد أرقام فيبانوتشي fibonacci

fun fibonacciSequence():Sequence<Long>{
    var a =0L
    var b =1L

    fun next():Long{
        val result = a + b
        a = b
        b = result
        return a
    }return generateSequence(::next)}
val y = fibonacciSequence().take(10).toList()
println(y)// => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

تزوّد Kotlin دوال عالية الرتبة للعمل مع المجموعات collections

val z =(1..9).map{it *3}.filter {it <20}.groupBy {it %2==0}.mapKeys {if(it.key)"even"else"odd"}
println(z)// => {odd=[3, 9, 15], even=[6, 12, 18]}

يمكن استخدام حلقة for مع أي شيء يؤمن التكرار.

for(c in "hello"){
    println(c)}

تعمل حلقات while بشكل مشابه لعملها في اللغات الأخرى

var ctr =0while(ctr <5){
    println(ctr)
    ctr++}do{
    println(ctr)
    ctr++}while(ctr <10)

يمكن استخدام if كتعبير يرجع القيم. لهذا السبب ليس هناك حاجة لمعامل التشغيل :? في Kotlin.

val num =5
val message =if(num %2==0)"even"else"odd"
println("$num is $message")// => 5 is odd

يمكن استخدام when كبديل لسلاسل if-else if

val i =10
when {
    i <7-> println("first block")
    fooString.startsWith("hello")-> println("second block")else-> println("else block")}

يمكن استخدام when مع المعطيات.

when (i){0,21-> println("0 or 21")
    in 1..20-> println("in the range 1 to 20")else-> println("none of the above")}

يمكن استخدام when كدالة ترجع القيم.

var result = when (i){0,21->"0 or 21"
    in 1..20->"in the range 1 to 20"else->"none of the above"}
println(result)

يمكننا التحقق فيما إذا كان الكائن object من نوع محدّد باستخدام معامل التشغيل is. إذا مرر الكائن فحص النوع type check عندها يمكن استخدام هذا النوع دون الموائمة بشكل صريح.

fun smartCastExample(x:Any):Boolean{if(x is Boolean){

X توائم أوتوماتيكيًا إلى Boolean

return x
   }elseif(x is Int){

X توائم أوتوماتيكيًا إلى Int

return x >0}elseif(x is String){

X توائم أوتوماتيكيًا إلى String

return x.isNotEmpty()}else{returnfalse}}
println(smartCastExample("Hello, world!"))// => true
println(smartCastExample(""))// => false
println(smartCastExample(5))// => true
println(smartCastExample(0))// => false
println(smartCastExample(true))// => true

تعمل الموائمة الذكيّة smartcast أيضًا مع كتلة when

fun smartCastWhenExample(x:Any)= when (x){
    is Boolean-> x
    is Int-> x >0
    is String-> x.isNotEmpty()else->false}

الملحقات Extensions هي طريقة لإضافة وظائف جديدة للصنف class. وهي مشابهة لدوال ملحقات #C

fun String.remove(c:Char):String{returnthis.filter {it != c}}
println("Hello, world!".remove('l'))// => Hello, word!

println(EnumExample.A)// => A
println(ObjectExample.hello())// => hello

أصناف Enum مشابهة لأنواع enum في جافا.

enumclassEnumExample{
    A, B, C
}

يمكن استخدام الكلمة المفتاحية object لإنشاء كائنات وحيدة. لا يمكننا تمثيلها ولكن يمكن أن نشير لحالتها الفريدة من خلال اسمها. وهذا مشابه لكائنات Scala singleton

object ObjectExample{
    fun hello():String{return"hello"}}

fun useObject(){ObjectExample.hello()
    val someRef:Any=ObjectExample//كماهي تمامًا objects نستخدم أسماء الكائنات  }

ترجمة -وبتصرّف- للمقال Learn kotlin in Y Minutes





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن