الفرق بين المراجعتين لصفحة: «Kotlin/basic syntax»

من موسوعة حسوب
طلا ملخص تعديل
ط إضافة العنوان
 
(3 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:البنية العامّة للغة Kotlin}}</noinclude>
<noinclude>{{DISPLAYTITLE:بنية البرمجة في لغة Kotlin}}</noinclude>
==تعريف الحزمة (Package)==
== تعريف الحزم (Package) ==
يُكتب توصيف الحزمة (package) في بداية الملف المصدريّ (source file) بالشكل الآتي:<syntaxhighlight lang="kotlin">
يُكتب توصيف الحزمة (package) في بداية الملف المصدريّ (source file) بالشكل الآتي:<syntaxhighlight lang="kotlin">
package my.demo
package my.demo
import java.util.*
import java.util.*
// ...
// ...
</syntaxhighlight>ولا يُشترط التوافق ما بين الحزمة (package) والمجلد الموجودة فيه (directory)، إذ من الممكن أن تتوضع الملفات المصدريّة عشوائيًّا في نظام الملفات.


المزيد عن [[Kotlin/packages|الحزم packages]].
 
==تعريف الدالة (Function)==
</syntaxhighlight>ولا يُشترط التوافق ما بين الحزمة (package) والمجلد الذي توجد فيه (directory)، إذ من الممكن أن تتوضع الملفات المصدريّة عشوائيًّا في نظام الملفات.
إن كانت الدالة بمتحولين من نوع Int وتعيد قيمةً بنوع Int أيضًا، يصبح تعريفها بالشكل:<syntaxhighlight lang="kotlin">
 
المزيد عن [[Kotlin/packages|الحزم (packages)]].
 
== تعريف الدوال (Function) ==
إن كانت الدالة بمتحولين من نوع <code>Int</code> وتعيد قيمةً بنوع <code>Int</code> أيضًا، فسيصبح تعريفها بالشكل:<syntaxhighlight lang="kotlin">
fun sum(a: Int, b: Int): Int {
fun sum(a: Int, b: Int): Int {
   return a + b
  return a + b
}
}
</syntaxhighlight>أما الشيفرة الآتية فهي لتعريف دالةٍ باسم sum تحتوي على تعبير (expression) دون التصريح عن نوع القيمة المعادة:<syntaxhighlight lang="kotlin">
 
 
</syntaxhighlight>أما الشيفرة الآتية فهي لتعريف دالةٍ باسم <code>sum</code> تحتوي على تعبيرٍ (expression) دون التصريح عن نوع القيمة المُعادَة:<syntaxhighlight lang="kotlin">
fun sum(a: Int, b: Int) = a + b
fun sum(a: Int, b: Int) = a + b
</syntaxhighlight>وإن لم تُعد الدالة أية قيمةٍ بمعنىً يصبح تعريفها على النحو الآتي: (الحالة الافتراضية هي Unit)<syntaxhighlight lang="kotlin">
</syntaxhighlight>وإن لم تُعد الدالة أيّة قيمةٍ ذات معنى يصبح تعريفها على النحو الآتي (يكون النوع المعاد <code>Unit</code> افتراضيًا):<syntaxhighlight lang="kotlin">
fun printSum(a: Int, b: Int): Unit {
fun printSum(a: Int, b: Int): Unit {
   println("sum of $a and $b is ${a + b}")
  println("sum of $a and $b is ${a + b}")
}
}
 
</syntaxhighlight>ويمكن الاستغناء عن كتابة النوع المُعاد <code>Unit</code> ليصبح التعريف بالشكل:<syntaxhighlight lang="kotlin">
 
</syntaxhighlight>ويمكن الاستغناء عن النوع المُعاد Unit ليصبح التعريف بالشكل:<syntaxhighlight lang="kotlin">
fun printSum(a: Int, b: Int) {
fun printSum(a: Int, b: Int) {
   println("sum of $a and $b is ${a + b}")
  println("sum of $a and $b is ${a + b}")
}
}
</syntaxhighlight>المزيد عن [[Kotlin/functions|الدوال (functions)]].


 
== تعريف المتحولات (Variables) ==
</syntaxhighlight>المزيد عن [[Kotlin/functions|الدوال functions]].
لتعريف متحوِّلٍ محليٍّ بإسنادٍ لمرة واحدة فقط (أي للقراءة فقط ولا يمكن إعطاؤه قيمةً جديدة) تُستخدَم إحدى الصيغ الآتية وذلك بالاعتماد على الكلمة المفتاحية <code>val</code>:<syntaxhighlight lang="kotlin">
==تعريف المتحولات (Variables)==
لتعريف متحوِّلٍ محليٍّ بإسنادٍ وحيد (للقراءة فقط ولا يمكن إعطاؤه قيمةً جديدة) تُستخدَم إحدى الصيغ الآتية:<syntaxhighlight lang="kotlin">
val a: Int = 1  // إسناد مباشر
val a: Int = 1  // إسناد مباشر


val b = 2   // يُعرَّف ضمنيًّا من النوع Int  
val b = 2   // يُعرَّف ضمنيًّا من النوع Int


val c: Int  // من الضروري تحديد النوع إن لم تُسند القيمة للمتحوّل مباشرةً
val c: Int  // من الضروري تحديد النوع إن لم تُسند القيمة للمتحوّل مباشرةً


c = 3       // إسنادٌ لمتحوّل مُعرَّف مسبقًا
c = 3       // إسنادٌ لمتحوّل مُعرَّف مسبقًا
 
</syntaxhighlight>ولتعريف متحوِّلٍ بقيمةٍ قابلةٍ للتعديل (أي أنّه mutable) تُستخدَم الكلمة المفتاحية <code>var</code> بالصيغة الآتية:<syntaxhighlight lang="kotlin">
 
</syntaxhighlight>ولتعريف متحوِّلٍ بقيمةٍ قابلةٍ للتعديل:<syntaxhighlight lang="kotlin">
var x = 5 // يُعرَّف ضمنيًا من النوع Int  
var x = 5 // يُعرَّف ضمنيًا من النوع Int  


سطر 45: سطر 45:




</syntaxhighlight>وقد تكون المتحولات واقعةً بمستوىً أعلى من البنية الحاليّة كما في المثال الآتي: (المتحولان PI و x يقعان في مستوى أعلى من الدالة incrementX)<syntaxhighlight lang="kotlin">
</syntaxhighlight>وقد تقع المتحولات بمستوىً أعلى من البنية الحاليّة (top-level variables) كما في المثال الآتي الذي يقع فيه المتحولان <code>PI</code> و <code>x</code> في مستوى أعلى من الدالة <code>incrementX</code>:<syntaxhighlight lang="kotlin">
val PI = 3.14
val PI = 3.14
var x = 0
var x = 0


fun incrementX() {
fun incrementX() {
   x += 1
  x += 1
}
}


</syntaxhighlight>المزيد عن [[Kotlin/properties|الخاصّيات (properties) والحقول (fields)]].


</syntaxhighlight>المزيد عن [[Kotlin/properties|الخاصّيات properties والحقول fields]].
== التعليقات (Comments) ==
==التعليقات (Comments)==
تدعم لغة Kotlin نوعين من التعليقات (كما هو الحال في لغتَي Java و [[JavaScript]])؛ وهما التعليقات السطريّة والتعليقات متعددة الأسطر وتكون صياغتهما بالشكل الآتي:<syntaxhighlight lang="kotlin">
تدعم لغة Kotlin نوعين من التعليقات (كما هو الحال في لغتَي Java و JavaScript)؛ وهما التعليقات السطريّة أو التعليقات بأكثر من سطر، وتكون صياغتهما بالشكل الآتي:<syntaxhighlight lang="kotlin">
//‎‎ تعليق بسطر واحد
//‎‎ تعليق بسطر واحد


/*‎‎ هذا التعليق
/*‎‎ هذا التعليق
بأكثر من سطر */
بأكثر من سطر */
</syntaxhighlight>وعلى عكس لغة Java يُمكن أن تتداخل التعليقات متعددة الأسطر (أي أن يقع تعليقٌ داخلَ تعليقٍ آخر).


المزيد عن [[Kotlin/kotlin doc|توضيح آلية توثيق الشيفرات بلغة Kotlin]].


</syntaxhighlight>وعلى عكس لغة Java يُمكن للتعليقات بأكثر من سطرٍ أن تتداخل (أي أن يقع تعليقٌ داخلَ تعليقٍ آخر).
== استخدام قوالب السلاسل النصية (String Templates) ==
 
ولمعرفة المزيد من التفاصيل عن التعليقات يمكن الانتقال لصفحة [https://kotlinlang.org/docs/reference/kotlin-doc.html توضيح آلية التوثيق للبرامج بلغة Kotlin] بالانكليزية.
==استخدام قوالب السلاسل النصيّة (String Templates)==
تكون صياغتها بالشكل الآتي:<syntaxhighlight lang="kotlin">
تكون صياغتها بالشكل الآتي:<syntaxhighlight lang="kotlin">
var a = 1
var a = 1
سطر 77: سطر 76:




</syntaxhighlight>المزيد عن [[Basic types|قوالب السلاسل النصية]].
</syntaxhighlight>المزيد عن [[Kotlin/basic types|قوالب السلاسل النصيّة (string templates)]].
==استخدام التعابير الشرطية (Conditional Expressions)==
 
توضِّح الدالة الآتية (لإعادة القيمة الأكبر من بين القيمتين a و b) طريقة صياغة الشرط if:<syntaxhighlight lang="kotlin">
== استخدام التعابير الشرطية (Conditional Expressions) ==
توضِّح الدالة الآتية والتي تعيد القيمة الأكبر من بين القيمتين <code>a</code> و<code>b</code> طريقة [[Kotlin/control flow|صياغة الشرط <code>if</code>]]:<syntaxhighlight lang="kotlin">
fun maxOf(a: Int, b: Int): Int {
fun maxOf(a: Int, b: Int): Int {
   if (a > b) {
  if (a > b) {
       return a
      return a
   } else {
  } else {
       return b
      return b
   }
  }
}
}
</syntaxhighlight>وكما يمكن استخدام [[Kotlin/control flow|الشرط <code>if</code>]] بصياغة تعبيريّة (expression) بالشكل الآتي:<syntaxhighlight lang="kotlin">
fun maxOf(a: Int, b: Int) = if (a > b) a else b
</syntaxhighlight>المزيد عن [[Kotlin/control flow|استخدام الشرط if]].


== استخدام القيم التي تقبل القيمة الفارغة Null والتحقق منها ==
يُقال عن المتحول المرجعيّ (reference variable) بأنّه nullable إن كان يقبل القيمة <code>null</code>، وهو المتحول الذي يُتاح الوصول إلى الكائن من خلاله.


</syntaxhighlight>وكما يمكن استخدام الشرط if بصياغة تعبيريّة بالشكل الآتي:<syntaxhighlight lang="kotlin">
ستعيد الدالة الآتية القيمة <code>null</code> إن لم تحتوِ السلسلة النصيّة <code>str</code> على قيمةٍ صحيحةٍ (<code>Int</code>):<syntaxhighlight lang="kotlin">
fun maxOf(a: Int, b: Int) = if (a > b) a else b
</syntaxhighlight>المزيد عن استخدام [[Kotlin/control flow if|الشرط if]].
==استخدام القيم التي تقبل القيمة الفارغة Null والتحقُّق منها==
عندما تكون القيمة null محتملة للمتحول المرجعي (reference) فيُقال عنه أنه nullable.
 
إن الدالة الآتية ستعيد قيمة null إن لم تحتوي السلسلة str على قيمةٍ صحيحة:<syntaxhighlight lang="kotlin">
fun parseInt(str: String): Int? {
fun parseInt(str: String): Int? {
   // ...
  // ...
}
}
 
</syntaxhighlight>أما الدالة الآتية (والتي تُظهِر ناتج جداء العددين الموجودين بالسلسلتين <code>arg1</code> و <code>arg2</code>) فستعيد القيمة <code>null</code>:<syntaxhighlight lang="kotlin">
 
</syntaxhighlight>أما الدالة الآتية (إخراج قيمة ناتج جداء العددين الموجودين بالسلسلتين arg1 و arg2) فتعيد قيمة null:<syntaxhighlight lang="kotlin">
fun printProduct(arg1: String, arg2: String) {
fun printProduct(arg1: String, arg2: String) {
   val x = parseInt(arg1) //‎‎ تحويل السلسلة النصيّة إلى قيمة عددية تُخزّن في المتحول
  val x = parseInt(arg1) //‎‎ تحويل السلسلة النصيّة إلى قيمة عددية تُخزّن في المتحول
   val y = parseInt(arg2)
  val y = parseInt(arg2)


   //‎‎ قد ينتج عن عملية الجداء حدوث خطأ في حال احتواء أحد المتحولين على قيمة null
  //‎‎ قد ينتج عن عملية الجداء حدوث خطأ في حال احتواء أحد المتحولين على قيمة null
   if (x != null && y != null) {
  if (x != null && y != null) {
       println(x * y)
      println(x * y)
   }
  }
 
  else {
   else {
      println("either '$arg1' or '$arg2' is not a number")
       println("either '$arg1' or '$arg2' is not a number")
  }  
   }    
}
}
</syntaxhighlight>أو بالشكل:<syntaxhighlight lang="kotlin">
</syntaxhighlight>أو بالشكل:<syntaxhighlight lang="kotlin">
// ...
// ...
if (x == null) {
if (x == null) {
   println("Wrong number format in arg1: '$arg1'")
  println("Wrong number format in arg1: '$arg1'")
   return
  return
}
}
if (y == null) {
if (y == null) {
   println("Wrong number format in arg2: '$arg2'")
  println("Wrong number format in arg2: '$arg2'")
   return
  return
}
}
println(x * y)
println(x * y)
</syntaxhighlight>المزيد عن [[Kotlin/null safety|القيمة الفارغة null وأمان استخدامها]].


 
== التحقق من النوع (Type Check) والتحويلات التلقائية بين الأنواع (Casting) ==
</syntaxhighlight>المزيد عن [[Kotlin/null safety|القيمة الفارغة null]].
يُستخدَم المعامل <code>is</code> للتحقُّق من أنّ قيمة التعبير البرمجي (expression) تتبع لأحد الأنواع المُعرَّفة في لغة Kotlin، وإذا ما تمّ التحقُّق من نوع القيمة غير القابلة للتغيير (immutable) للمتغيّرات المحليّة (local variable) أو من قيمة إحدى الخاصّيات (property) فلا حاجة حينئذٍ للتصريح عن تحويلها (casting)، كما هو واضح بالشيفرة الآتية:<syntaxhighlight lang="kotlin">
==التحقُّق من النوع والتحويلات التلقائية بين الأنواع (Casting)==
يُستخدَم المعامل is للتحقق من أنّ قيمة التعبير تتبع لأحد الأنواع، وإذا ما تمّ التحقُّق من القيمة الثابتة للمتغيّرات المحليّة (immutable local variable) أو من قيمة إحدى الخاصّيات فلا حاجة للتصريح عن تحويلها (casting)، كما هو واضح بالشيفرة الآتية:<syntaxhighlight lang="kotlin">
```
fun getStringLength(obj: Any): Int? {
fun getStringLength(obj: Any): Int? {
   if (obj is String) {
  if (obj is String) {
       //‎‎سيُحوّل الكائن تلقائيًا في هذا الجزء إلى نوع String
      //‎‎ سيُحوّل الكائن تلقائيًا في هذا الجزء إلى نوع String
       return obj.length
      // ولا داعي لإجراء التحويل بشكل صريح
   }
      return obj.length
 
  }
   //‎‎وفي هذا الجزء سيبقى من النوع Any
  //‎‎ وفي هذا الجزء سيبقى من النوع Any
   return null
  return null
}
}
</syntaxhighlight>أو بالشكل:<syntaxhighlight lang="kotlin">
</syntaxhighlight>أو بالشكل:<syntaxhighlight lang="kotlin">
fun getStringLength(obj: Any): Int? {
fun getStringLength(obj: Any): Int? {
   if (obj !is String) return null
  if (obj !is String) return null
   //‎‎سيُحوّل الكائن obj تلقائيًا إلى نوع String في هذا الجزء
  //‎‎ سيُحوّل الكائن obj  
   return obj.length
  // تلقائيًا إلى نوع String  
  return obj.length
}
}
 
</syntaxhighlight>أو بشكلٍ آخر:<syntaxhighlight lang="kotlin">
</syntaxhighlight>أو بشكل آخر:<syntaxhighlight lang="kotlin">
fun getStringLength(obj: Any): Int? {
fun getStringLength(obj: Any): Int? {
   //‎‎سيُحوّل الكائن الموجود على يمين المعامل تلقائيًا إلى نوع String
  //‎‎ سيُحوّل الكائن الموجود على يمين المعامل تلقائيًا إلى النوع String
   if (obj is String && obj.length > 0) {
  if (obj is String && obj.length > 0) {
       return obj.length
      return obj.length
   }
  }
   return null
  return null
}
}
</syntaxhighlight>المزيد عن [[Kotlin/classes|الأصناف (classes)]] و<nowiki/>[[Kotlin/typecasts|التحويل ما بين الأنواع (type casts)]].


</syntaxhighlight>المزيد عن [[Kotlin/classes|الأصناف classes]] و<nowiki/>[[Kotlin/typecasts|التحويل ما بين الأنواع type casts]].
== استخدام حلقة <code>for</code> ==
==استخدام حلقة For==
تُكتب حلقة <code>for</code> بالشكل الآتي:<syntaxhighlight lang="kotlin">
تُكتب حلقة for بالشكل الآتي:<syntaxhighlight lang="kotlin">
val items = listOf("apple", "banana", "kiwi")
val items = listOf("apple", "banana", "kiwi")


for (item in items) {
for (item in items) {
   println(item)
  println(item)
}
}
 
</syntaxhighlight>إذ يُستخدَم المعامل <code>in</code> للمرور بكافة العناصر الموجودة في المجموعة <code>items</code>، ويوضِّح المثال الآتي استخدام حلقة <code>for</code> أيضًا ولكن بالاعتماد على فهارس (indices) العناصر بدلًا من العناصر بحدّ ذاتها:<syntaxhighlight lang="kotlin">
 
</syntaxhighlight>إذ يُستخدَم المعامل in للمرور بكافة العناصر الموجودة في المجموعة items.
 
ويوضح المثال الآتي استخدام حلقة for أيضًا ولكن مع الأدلة (indices) للعناصر بدلًا من العناصر نفسها:<syntaxhighlight lang="kotlin">
val items = listOf("apple", "banana", "kiwi")
val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
for (index in items.indices) {
   println("item at $index is ${items[index]}")
  println("item at $index is ${items[index]}")
}
}




</syntaxhighlight>المزيد عن [[Kotlin/control flow for|حلقة for]].
</syntaxhighlight>المزيد عن [[Kotlin/control flow|حلقة <code>for</code>]].
==استخدام حلقة While==
 
== استخدام حلقة <code>while</code> ==
يكون استخدامها وفق الصيغة الآتية:<syntaxhighlight lang="kotlin">
يكون استخدامها وفق الصيغة الآتية:<syntaxhighlight lang="kotlin">
val items = listOf("apple", "banana", "kiwi")
val items = listOf("apple", "banana", "kiwi")
var index = 0
var index = 0
while (index < items.size) {
while (index < items.size) {
   println("item at $index is ${items[index]}")
  println("item at $index is ${items[index]}")
   index++
  index++
}
}
</syntaxhighlight>إذ ستستمر الحلقة لحين الوصول إلى آخر عنصر في المجموعة (أي حتى وصول المتحول <code>index</code> إلى قيمة فهرس العنصر الأخير).


المزيد عن [[Kotlin/control flow|حلقة <code>while</code>]].


</syntaxhighlight>حيث ستستمر الحلقة لحين الوصول إلى آخر عنصر في المجموعة (بلوغ المتحول index قيمة دليل العنصر الأخير).
== استخدام التعبير <code>when</code> ==
 
يُستخدَم التعبير <code>when</code> للتحقُّق من أنّ قيمةً ما (value) أو أحدَ المتغيِّرات (variable) أو إحدى خاصّيات الكائن (properties)  توافق إحدى الحالات المذكورة في التعبير  بالشكل الآتي:<syntaxhighlight lang="kotlin">
المزيد عن [[Kotlin/control flow while|حلقة while]].
==استخدام التعبير When==
يُستخدَم التعبير when للتحقق من قيمة أو إحدى خاصّيات الكائن أو المتحوِّل بالشكل الآتي:<syntaxhighlight lang="kotlin">
fun describe(obj: Any): String =
fun describe(obj: Any): String =
when (obj) {
when (obj) {
   1          -> "One"
  1        -> "One"
   "Hello"    -> "Greeting"
  "Hello"    -> "Greeting"
   is Long    -> "Long"
  is Long    -> "Long"
   !is String -> "Not a string"
  !is String -> "Not a string"
   else       -> "Unknown"
  else       -> "Unknown"
}
}
</syntaxhighlight>المزيد عن [[Kotlin/control flow|التعبير <code>when</code>]].


 
== استخدام المجالات (Ranges) ==
</syntaxhighlight>المزيد عن [[Kotlin/control flow when|التعبير when]].
يُستخَدم المعامل <code>in</code> للتأكُّد من وقوع قيمةٍ ما ضمن المجال المُحدَّد، وهذا يتَّضِح في المثال الآتي:<syntaxhighlight lang="kotlin">
==استخدام المجالات (Ranges)==
يُستخَدم المعامل in للتأكد من وقوع قيمةٍ ما ضمن مجالٍ مُحدَّد، وهذا يتَّضح عبر المثال الآتي:<syntaxhighlight lang="kotlin">
val x = 10
val x = 10
val y = 9
val y = 9


if (x in 1..y+1) { // المجال يمتد من قيمة 1 وحتى قيمة y+1
if (x in 1..y+1) { // المجال يمتد من قيمة 1 وحتى قيمة y+1
   println("fits in range")
  println("fits in range")
}
}
 
</syntaxhighlight>كما ويمكن استخدامه للتحقُّق من وقوع القيمة خارج هذا المجال، بالشكل الآتي:<syntaxhighlight lang="kotlin">
</syntaxhighlight>كما ويمكن استخدامه للتحقُّق من أنّ القيمة خارج هذا المجال، بالشكل الآتي:<syntaxhighlight lang="kotlin">
val list = listOf("a", "b", "c")
val list = listOf("a", "b", "c")


if (-1 !in 0..list.lastIndex) { // المجال يمتد من 0 وحتى قيمة الدليل الأخير
if (-1 !in 0..list.lastIndex) { // المجال يمتد من 0 وحتى قيمة الفهرس الأخير
   println("-1 is out of range")
  println("-1 is out of range")
}
}


if (list.size !in list.indices) {
if (list.size !in list.indices) {
   println("list size is out of valid list indices range too")
  println("list size is out of valid list indices range too")
}
}
 
</syntaxhighlight>ولتكرار عددٍ من التعليمات في مجالٍ مُحدَّدٍ، تصبح الصيغة بالشكل:<syntaxhighlight lang="kotlin">
 
for (x in 1..5) { // يمتد المجال من 1 حتى 5
</syntaxhighlight>ولتكرار عددٍ من التعليمات في مجالٍ مُحدَّدٍ، تصبح الصياغة بالشكل:<syntaxhighlight lang="kotlin">
  print(x)
for (x in 1..5) { // المجال يمتد من 1 حتى 5
   print(x)
}
}
 
</syntaxhighlight>أما للتكرار المتسلسل وفق خطوة <code>step</code>:<syntaxhighlight lang="kotlin">
 
</syntaxhighlight>أما للتكرار المتسلسل وفق خطوة step:<syntaxhighlight lang="kotlin">
for (x in 1..10 step 2) { //يبدأ المجال من القيمة 1 وينتهي بالقيمة 10 وبخطوةٍ مقدارها 2
for (x in 1..10 step 2) { //يبدأ المجال من القيمة 1 وينتهي بالقيمة 10 وبخطوةٍ مقدارها 2
   print(x)
  print(x)
}
}
println()
println()
for (x in 9 downTo 0 step 3) { // يبدأ المجال بالقيمة 9 وينتهي بشكل تنازليّ عند القيمة 0 بخطوةٍ مقدارها 3
for (x in 9 downTo 0 step 3) { // يبدأ المجال بالقيمة 9 وينتهي بشكل تنازليّ عند القيمة 0 بخطوةٍ مقدارها 3
   print(x)
  print(x)
}
}
</syntaxhighlight>المزيد عن [[Kotlin/ranges|المجالات (ranges)]].


 
== استخدام المجموعات (Collections) ==
</syntaxhighlight>المزيد عن [[Kotlin/ranges|المجالات ranges]].
يكون المرور على العناصر الموجودة في المجموعة بالشكل الآتي:<syntaxhighlight lang="kotlin">
==استخدام المجموعات (Collections)==
يُمكن تنفيذ التكرار على العناصر الموجودة في المجموعة بالشكل الآتي:<syntaxhighlight lang="kotlin">
for (item in items) {
for (item in items) {
   println(item)
  println(item)
}
}
</syntaxhighlight>أما للتأكُّد من وجود عنصرٍ ما ضمن المجموعة باستخدام المعامل in تصبح الصياغة بالشكل الآتي:<syntaxhighlight lang="kotlin">
 
 
</syntaxhighlight>أما للتأكُّد من وجود عنصرٍ ما ضمن المجموعة باستخدام المعامل <code>in</code> فتصبح الصيغة بالشكل الآتي:<syntaxhighlight lang="kotlin">
when {
when {
  "orange" in items -> println("juicy")
  "orange" in items -> println("juicy")
   "apple" in items -> println("apple is fine too")
  "apple" in items -> println("apple is fine too")
}
}
</syntaxhighlight>كما ويمكن استخدام تعابير lambda لتصنيف وتعيين المجموعات، كما في الشيفرة الآتية:<syntaxhighlight lang="kotlin">
</syntaxhighlight>كما ويمكن استخدام [[Kotlin/lambdas|تعابير lambda]] لتصنيف وتعيين المجموعات، كما في الشيفرة الآتية:<syntaxhighlight lang="kotlin">
fruits
fruits
.filter { it.startsWith("a") }
.filter { it.startsWith("a") }
سطر 266: سطر 244:
.map { it.toUpperCase() }
.map { it.toUpperCase() }
.forEach { println(it) }
.forEach { println(it) }
</syntaxhighlight>المزيد عن [[Kotlin/lambdas|الدوال عالية المستوى (top-level functions) وتعابير lambdas]].


 
== إنشاء الأصناف (Classes) والكائنات الناتجة عنها (Objects) ==
</syntaxhighlight>المزيد عن [[Kotlin/lambdas|الدوال عالية المستوى وتعابير lambdas]].
==إنشاء الأصناف (Classes) والكائنات الناتجة عنها (Objects)==
يُوضِّح المثال الآتي إنشاء كائنَين من صنفَين مختلفين:<syntaxhighlight lang="kotlin">
يُوضِّح المثال الآتي إنشاء كائنَين من صنفَين مختلفين:<syntaxhighlight lang="kotlin">
val rectangle = Rectangle(5.0, 2.0) // لا حاجة لكلمة new
val rectangle = Rectangle(5.0, 2.0) // لا حاجة للكلمة المفتاحيّة new


val triangle = Triangle(3.0, 4.0, 5.0)
val triangle = Triangle(3.0, 4.0, 5.0)
</syntaxhighlight>المزيد عن [[Kotlin/classes|الأصناف classes]] و<nowiki/>[[Kotlin/object declarations|الكائنات objects]].


 
== مصادر ==
</syntaxhighlight>المزيد عن [[Kotlin/classes|الأصناف classes]] و<nowiki/>[[Kotlin/object declarations|الكائنات objects]].
* [https://kotlinlang.org/docs/reference/basic-syntax.html البنية العامّة في التوثيق الرسميّ للغة Kotlin.]
==مصادر==
[[تصنيف:Kotlin]]
* [https://kotlinlang.org/docs/reference/basic-syntax.html صفحة البنية العامّة في توثيق لغة Kotlin]

المراجعة الحالية بتاريخ 06:00، 15 مايو 2018

تعريف الحزم (Package)

يُكتب توصيف الحزمة (package) في بداية الملف المصدريّ (source file) بالشكل الآتي:

package my.demo
import java.util.*
// ...

ولا يُشترط التوافق ما بين الحزمة (package) والمجلد الذي توجد فيه (directory)، إذ من الممكن أن تتوضع الملفات المصدريّة عشوائيًّا في نظام الملفات.

المزيد عن الحزم (packages).

تعريف الدوال (Function)

إن كانت الدالة بمتحولين من نوع Int وتعيد قيمةً بنوع Int أيضًا، فسيصبح تعريفها بالشكل:

fun sum(a: Int, b: Int): Int {
  return a + b
}

أما الشيفرة الآتية فهي لتعريف دالةٍ باسم sum تحتوي على تعبيرٍ (expression) دون التصريح عن نوع القيمة المُعادَة:

fun sum(a: Int, b: Int) = a + b

وإن لم تُعد الدالة أيّة قيمةٍ ذات معنى يصبح تعريفها على النحو الآتي (يكون النوع المعاد 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}")
}

المزيد عن الدوال (functions).

تعريف المتحولات (Variables)

لتعريف متحوِّلٍ محليٍّ بإسنادٍ لمرة واحدة فقط (أي للقراءة فقط ولا يمكن إعطاؤه قيمةً جديدة) تُستخدَم إحدى الصيغ الآتية وذلك بالاعتماد على الكلمة المفتاحية val:

val a: Int = 1  // إسناد مباشر

val b = 2   // يُعرَّف ضمنيًّا من النوع Int

val c: Int  // من الضروري تحديد النوع إن لم تُسند القيمة للمتحوّل مباشرةً

c = 3       // إسنادٌ لمتحوّل مُعرَّف مسبقًا

ولتعريف متحوِّلٍ بقيمةٍ قابلةٍ للتعديل (أي أنّه mutable) تُستخدَم الكلمة المفتاحية var بالصيغة الآتية:

var x = 5 // يُعرَّف ضمنيًا من النوع Int 

x += 1

وقد تقع المتحولات بمستوىً أعلى من البنية الحاليّة (top-level variables) كما في المثال الآتي الذي يقع فيه المتحولان PI و x في مستوى أعلى من الدالة incrementX:

val PI = 3.14
var x = 0

fun incrementX() {
  x += 1
}

المزيد عن الخاصّيات (properties) والحقول (fields).

التعليقات (Comments)

تدعم لغة Kotlin نوعين من التعليقات (كما هو الحال في لغتَي Java و JavaScript)؛ وهما التعليقات السطريّة والتعليقات متعددة الأسطر وتكون صياغتهما بالشكل الآتي:

//‎‎ تعليق بسطر واحد

/*‎‎ هذا التعليق
بأكثر من سطر */

وعلى عكس لغة Java يُمكن أن تتداخل التعليقات متعددة الأسطر (أي أن يقع تعليقٌ داخلَ تعليقٍ آخر).

المزيد عن توضيح آلية توثيق الشيفرات بلغة Kotlin.

استخدام قوالب السلاسل النصية (String Templates)

تكون صياغتها بالشكل الآتي:

var a = 1
//‎‎ اسم بسيط ضمن قالب نصيّ
val s1 = "a is $a"

a = 2
//‎‎ تعبيرٌ عشوائيّ ضمن قالب نصيّ
val s2 = "${s1.replace("is", "was")}, but now is $a"

المزيد عن قوالب السلاسل النصيّة (string templates).

استخدام التعابير الشرطية (Conditional Expressions)

توضِّح الدالة الآتية والتي تعيد القيمة الأكبر من بين القيمتين a وb طريقة صياغة الشرط if:

fun maxOf(a: Int, b: Int): Int {
  if (a > b) {
      return a
  } else {
      return b
  }
}

وكما يمكن استخدام الشرط if بصياغة تعبيريّة (expression) بالشكل الآتي:

fun maxOf(a: Int, b: Int) = if (a > b) a else b

المزيد عن استخدام الشرط if.

استخدام القيم التي تقبل القيمة الفارغة Null والتحقق منها

يُقال عن المتحول المرجعيّ (reference variable) بأنّه nullable إن كان يقبل القيمة null، وهو المتحول الذي يُتاح الوصول إلى الكائن من خلاله.

ستعيد الدالة الآتية القيمة null إن لم تحتوِ السلسلة النصيّة str على قيمةٍ صحيحةٍ (Int):

fun parseInt(str: String): Int? {
  // ...
}

أما الدالة الآتية (والتي تُظهِر ناتج جداء العددين الموجودين بالسلسلتين arg1 و arg2) فستعيد القيمة null:

fun printProduct(arg1: String, arg2: String) {
  val x = parseInt(arg1) //‎‎ تحويل السلسلة النصيّة إلى قيمة عددية تُخزّن في المتحول
  val y = parseInt(arg2)

  //‎‎ قد ينتج عن عملية الجداء حدوث خطأ في حال احتواء أحد المتحولين على قيمة null
  if (x != null && y != null) {
      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
}
println(x * y)

المزيد عن القيمة الفارغة null وأمان استخدامها.

التحقق من النوع (Type Check) والتحويلات التلقائية بين الأنواع (Casting)

يُستخدَم المعامل is للتحقُّق من أنّ قيمة التعبير البرمجي (expression) تتبع لأحد الأنواع المُعرَّفة في لغة Kotlin، وإذا ما تمّ التحقُّق من نوع القيمة غير القابلة للتغيير (immutable) للمتغيّرات المحليّة (local variable) أو من قيمة إحدى الخاصّيات (property) فلا حاجة حينئذٍ للتصريح عن تحويلها (casting)، كما هو واضح بالشيفرة الآتية:

fun getStringLength(obj: Any): Int? {
  if (obj is String) {
      //‎‎ سيُحوّل الكائن تلقائيًا في هذا الجزء إلى نوع String
      // ولا داعي لإجراء التحويل بشكل صريح
      return obj.length
  }
  //‎‎ وفي هذا الجزء سيبقى من النوع Any
  return null
}

أو بالشكل:

fun getStringLength(obj: Any): Int? {
  if (obj !is String) return null
  //‎‎ سيُحوّل الكائن obj 
  // تلقائيًا إلى نوع String 
  return obj.length
}

أو بشكلٍ آخر:

fun getStringLength(obj: Any): Int? {
  //‎‎ سيُحوّل الكائن الموجود على يمين المعامل تلقائيًا إلى النوع String
  if (obj is String && obj.length > 0) {
      return obj.length
  }
  return null
}

المزيد عن الأصناف (classes) والتحويل ما بين الأنواع (type casts).

استخدام حلقة for

تُكتب حلقة for بالشكل الآتي:

val items = listOf("apple", "banana", "kiwi")

for (item in items) {
  println(item)
}

إذ يُستخدَم المعامل in للمرور بكافة العناصر الموجودة في المجموعة items، ويوضِّح المثال الآتي استخدام حلقة for أيضًا ولكن بالاعتماد على فهارس (indices) العناصر بدلًا من العناصر بحدّ ذاتها:

val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
  println("item at $index is ${items[index]}")
}

المزيد عن حلقة for.

استخدام حلقة while

يكون استخدامها وفق الصيغة الآتية:

val items = listOf("apple", "banana", "kiwi")
var index = 0

while (index < items.size) {
  println("item at $index is ${items[index]}")
  index++
}

إذ ستستمر الحلقة لحين الوصول إلى آخر عنصر في المجموعة (أي حتى وصول المتحول index إلى قيمة فهرس العنصر الأخير).

المزيد عن حلقة while.

استخدام التعبير when

يُستخدَم التعبير when للتحقُّق من أنّ قيمةً ما (value) أو أحدَ المتغيِّرات (variable) أو إحدى خاصّيات الكائن (properties) توافق إحدى الحالات المذكورة في التعبير  بالشكل الآتي:

fun describe(obj: Any): String =
when (obj) {
  1        -> "One"
  "Hello"    -> "Greeting"
  is Long    -> "Long"
  !is String -> "Not a string"
  else       -> "Unknown"
}

المزيد عن التعبير when.

استخدام المجالات (Ranges)

يُستخَدم المعامل in للتأكُّد من وقوع قيمةٍ ما ضمن المجال المُحدَّد، وهذا يتَّضِح في المثال الآتي:

val x = 10
val y = 9

if (x in 1..y+1) { // المجال يمتد من قيمة 1 وحتى قيمة y+1
  println("fits in range")
}

كما ويمكن استخدامه للتحقُّق من وقوع القيمة خارج هذا المجال، بالشكل الآتي:

val list = listOf("a", "b", "c")

if (-1 !in 0..list.lastIndex) { // المجال يمتد من 0 وحتى قيمة الفهرس الأخير
  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) { // يمتد المجال من 1 حتى 5
  print(x)
}

أما للتكرار المتسلسل وفق خطوة step:

for (x in 1..10 step 2) { //يبدأ المجال من القيمة 1 وينتهي بالقيمة 10 وبخطوةٍ مقدارها 2
  print(x)
}
println()
for (x in 9 downTo 0 step 3) { // يبدأ المجال بالقيمة 9 وينتهي بشكل تنازليّ عند القيمة 0 بخطوةٍ مقدارها 3
  print(x)
}

المزيد عن المجالات (ranges).

استخدام المجموعات (Collections)

يكون المرور على العناصر الموجودة في المجموعة بالشكل الآتي:

for (item in items) {
  println(item)
}

أما للتأكُّد من وجود عنصرٍ ما ضمن المجموعة باستخدام المعامل in فتصبح الصيغة بالشكل الآتي:

when {
  "orange" in items -> println("juicy")
  "apple" in items -> println("apple is fine too")
}

كما ويمكن استخدام تعابير lambda لتصنيف وتعيين المجموعات، كما في الشيفرة الآتية:

fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { println(it) }

المزيد عن الدوال عالية المستوى (top-level functions) وتعابير lambdas.

إنشاء الأصناف (Classes) والكائنات الناتجة عنها (Objects)

يُوضِّح المثال الآتي إنشاء كائنَين من صنفَين مختلفين:

val rectangle = Rectangle(5.0, 2.0) // لا حاجة للكلمة المفتاحيّة new

val triangle = Triangle(3.0, 4.0, 5.0)

المزيد عن الأصناف classes والكائنات objects.

مصادر