الفرق بين المراجعتين لصفحة: «Kotlin/basic syntax»
ط إضافة تصنيف |
ط إضافة العنوان |
||
(1 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE: | <noinclude>{{DISPLAYTITLE:بنية البرمجة في لغة Kotlin}}</noinclude> | ||
==تعريف | == تعريف الحزم (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.* | ||
// ... | // ... | ||
المزيد عن [[Kotlin/packages|الحزم packages]]. | |||
==تعريف | </syntaxhighlight>ولا يُشترط التوافق ما بين الحزمة (package) والمجلد الذي توجد فيه (directory)، إذ من الممكن أن تتوضع الملفات المصدريّة عشوائيًّا في نظام الملفات. | ||
إن كانت الدالة بمتحولين من نوع <code>Int</code> وتعيد قيمةً بنوع <code>Int</code> أيضًا، | |||
المزيد عن [[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 | |||
} | } | ||
</syntaxhighlight>أما الشيفرة الآتية فهي لتعريف دالةٍ باسم <code>sum</code> تحتوي على | |||
</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>وإن لم تُعد الدالة | </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}") | |||
} | } | ||
</syntaxhighlight>ويمكن الاستغناء عن كتابة النوع المُعاد <code>Unit</code> ليصبح التعريف بالشكل:<syntaxhighlight lang="kotlin"> | |||
</syntaxhighlight>ويمكن الاستغناء عن النوع المُعاد <code>Unit</code> ليصبح التعريف بالشكل:<syntaxhighlight lang="kotlin"> | |||
fun printSum(a: Int, b: Int) { | fun printSum(a: Int, b: Int) { | ||
println("sum of $a and $b is ${a + b}") | |||
} | } | ||
</syntaxhighlight>المزيد عن [[Kotlin/functions|الدوال (functions)]]. | |||
== تعريف المتحولات (Variables) == | |||
لتعريف متحوِّلٍ محليٍّ بإسنادٍ لمرة واحدة فقط (أي للقراءة فقط ولا يمكن إعطاؤه قيمةً جديدة) تُستخدَم إحدى الصيغ الآتية وذلك بالاعتماد على الكلمة المفتاحية <code>val</code>:<syntaxhighlight lang="kotlin"> | |||
==تعريف المتحولات (Variables)== | |||
لتعريف متحوِّلٍ محليٍّ بإسنادٍ | |||
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>وقد | </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 | |||
} | } | ||
</syntaxhighlight>المزيد عن [[Kotlin/properties|الخاصّيات (properties) والحقول (fields)]]. | |||
== التعليقات (Comments) == | |||
==التعليقات (Comments)== | تدعم لغة Kotlin نوعين من التعليقات (كما هو الحال في لغتَي Java و [[JavaScript]])؛ وهما التعليقات السطريّة والتعليقات متعددة الأسطر وتكون صياغتهما بالشكل الآتي:<syntaxhighlight lang="kotlin"> | ||
تدعم لغة Kotlin نوعين من التعليقات (كما هو الحال في لغتَي Java و [[JavaScript]])؛ وهما التعليقات السطريّة | |||
// تعليق بسطر واحد | // تعليق بسطر واحد | ||
/* هذا التعليق | /* هذا التعليق | ||
بأكثر من سطر */ | بأكثر من سطر */ | ||
</syntaxhighlight>وعلى عكس لغة Java يُمكن أن تتداخل التعليقات متعددة الأسطر (أي أن يقع تعليقٌ داخلَ تعليقٍ آخر). | |||
المزيد عن [[Kotlin/kotlin doc|توضيح آلية توثيق الشيفرات بلغة Kotlin]]. | |||
== استخدام قوالب السلاسل النصية (String Templates) == | |||
==استخدام قوالب السلاسل | |||
تكون صياغتها بالشكل الآتي:<syntaxhighlight lang="kotlin"> | تكون صياغتها بالشكل الآتي:<syntaxhighlight lang="kotlin"> | ||
var a = 1 | var a = 1 | ||
سطر 77: | سطر 76: | ||
</syntaxhighlight>المزيد عن [[Kotlin/ | </syntaxhighlight>المزيد عن [[Kotlin/basic types|قوالب السلاسل النصيّة (string templates)]]. | ||
==استخدام التعابير الشرطية (Conditional Expressions)== | |||
توضِّح الدالة الآتية | == استخدام التعابير الشرطية (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) { | |||
return a | |||
} else { | |||
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>، وهو المتحول الذي يُتاح الوصول إلى الكائن من خلاله. | |||
ستعيد الدالة الآتية القيمة <code>null</code> إن لم تحتوِ السلسلة النصيّة <code>str</code> على قيمةٍ صحيحةٍ (<code>Int</code>):<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>أما الدالة الآتية ( | |||
fun printProduct(arg1: String, arg2: String) { | 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") | |||
} | |||
} | } | ||
</syntaxhighlight>أو بالشكل:<syntaxhighlight lang="kotlin"> | </syntaxhighlight>أو بالشكل:<syntaxhighlight lang="kotlin"> | ||
// ... | // ... | ||
if (x == null) { | if (x == null) { | ||
println("Wrong number format in arg1: '$arg1'") | |||
return | |||
} | } | ||
if (y == null) { | if (y == null) { | ||
println("Wrong number format in arg2: '$arg2'") | |||
return | |||
} | } | ||
println(x * y) | println(x * y) | ||
</syntaxhighlight>المزيد عن [[Kotlin/null safety|القيمة الفارغة null وأمان استخدامها]]. | |||
== التحقق من النوع (Type Check) والتحويلات التلقائية بين الأنواع (Casting) == | |||
يُستخدَم المعامل <code>is</code> للتحقُّق من أنّ قيمة التعبير البرمجي (expression) تتبع لأحد الأنواع المُعرَّفة في لغة Kotlin، وإذا ما تمّ التحقُّق من نوع القيمة غير القابلة للتغيير (immutable) للمتغيّرات المحليّة (local variable) أو من قيمة إحدى الخاصّيات (property) فلا حاجة حينئذٍ للتصريح عن تحويلها (casting)، كما هو واضح بالشيفرة الآتية:<syntaxhighlight lang="kotlin"> | |||
== | |||
يُستخدَم المعامل <code>is</code> | |||
fun getStringLength(obj: Any): Int? { | fun getStringLength(obj: Any): Int? { | ||
if (obj is String) { | |||
// سيُحوّل الكائن تلقائيًا في هذا الجزء إلى نوع String | |||
// ولا داعي لإجراء التحويل بشكل صريح | |||
return obj.length | |||
} | |||
// وفي هذا الجزء سيبقى من النوع Any | |||
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 | |||
// سيُحوّل الكائن obj | |||
// تلقائيًا إلى نوع String | |||
return obj.length | |||
} | } | ||
</syntaxhighlight>أو بشكلٍ آخر:<syntaxhighlight lang="kotlin"> | |||
</syntaxhighlight>أو | |||
fun getStringLength(obj: Any): Int? { | fun getStringLength(obj: Any): Int? { | ||
// سيُحوّل الكائن الموجود على يمين المعامل تلقائيًا إلى النوع String | |||
if (obj is String && obj.length > 0) { | |||
return obj.length | |||
} | |||
return null | |||
} | } | ||
</syntaxhighlight>المزيد عن [[Kotlin/classes|الأصناف (classes)]] و<nowiki/>[[Kotlin/typecasts|التحويل ما بين الأنواع (type casts)]]. | |||
< | == استخدام حلقة <code>for</code> == | ||
تُكتب حلقة <code>for</code> بالشكل الآتي:<syntaxhighlight lang="kotlin"> | تُكتب حلقة <code>for</code> بالشكل الآتي:<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) | |||
} | } | ||
</syntaxhighlight>إذ يُستخدَم المعامل <code>in</code> للمرور بكافة العناصر الموجودة في المجموعة <code>items</code>، ويوضِّح المثال الآتي استخدام حلقة <code>for</code> أيضًا ولكن بالاعتماد على فهارس (indices) العناصر بدلًا من العناصر بحدّ ذاتها:<syntaxhighlight lang="kotlin"> | |||
</syntaxhighlight>إذ يُستخدَم المعامل <code>in</code> للمرور بكافة العناصر الموجودة في المجموعة <code>items</code> | |||
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]}") | |||
} | } | ||
</syntaxhighlight>المزيد عن [[Kotlin/control flow | </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]}") | |||
index++ | |||
} | } | ||
</syntaxhighlight>إذ ستستمر الحلقة لحين الوصول إلى آخر عنصر في المجموعة (أي حتى وصول المتحول <code>index</code> إلى قيمة فهرس العنصر الأخير). | |||
المزيد عن [[Kotlin/control flow|حلقة <code>while</code>]]. | |||
== استخدام التعبير <code>when</code> == | |||
يُستخدَم التعبير <code>when</code> للتحقُّق من أنّ قيمةً ما (value) أو أحدَ المتغيِّرات (variable) أو إحدى خاصّيات الكائن (properties) توافق إحدى الحالات المذكورة في التعبير بالشكل الآتي:<syntaxhighlight lang="kotlin"> | |||
يُستخدَم التعبير <code>when</code> | |||
fun describe(obj: Any): String = | fun describe(obj: Any): String = | ||
when (obj) { | when (obj) { | ||
1 -> "One" | |||
"Hello" -> "Greeting" | |||
is Long -> "Long" | |||
!is String -> "Not a string" | |||
else -> "Unknown" | |||
} | } | ||
</syntaxhighlight>المزيد عن [[Kotlin/control flow|التعبير <code>when</code>]]. | |||
== استخدام المجالات (Ranges) == | |||
يُستخَدم المعامل <code>in</code> للتأكُّد من وقوع قيمةٍ ما ضمن المجال المُحدَّد، وهذا يتَّضِح في المثال الآتي:<syntaxhighlight lang="kotlin"> | |||
==استخدام المجالات (Ranges)== | |||
يُستخَدم المعامل <code>in</code> | |||
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") | |||
} | } | ||
</syntaxhighlight>كما ويمكن استخدامه للتحقُّق من وقوع القيمة خارج هذا المجال، بالشكل الآتي:<syntaxhighlight lang="kotlin"> | |||
</syntaxhighlight>كما ويمكن استخدامه للتحقُّق من | |||
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") | |||
} | } | ||
if (list.size !in list.indices) { | if (list.size !in list.indices) { | ||
println("list size is out of valid list indices range too") | |||
} | } | ||
</syntaxhighlight>ولتكرار عددٍ من التعليمات في مجالٍ مُحدَّدٍ، تصبح الصيغة بالشكل:<syntaxhighlight lang="kotlin"> | |||
for (x in 1..5) { // يمتد المجال من 1 حتى 5 | |||
</syntaxhighlight>ولتكرار عددٍ من التعليمات في مجالٍ مُحدَّدٍ، تصبح | print(x) | ||
for (x in 1..5) { // المجال | |||
} | } | ||
</syntaxhighlight>أما للتكرار المتسلسل وفق خطوة <code>step</code>:<syntaxhighlight lang="kotlin"> | </syntaxhighlight>أما للتكرار المتسلسل وفق خطوة <code>step</code>:<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) | |||
} | } | ||
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) | |||
} | } | ||
</syntaxhighlight>المزيد عن [[Kotlin/ranges|المجالات (ranges)]]. | |||
== استخدام المجموعات (Collections) == | |||
يكون المرور على العناصر الموجودة في المجموعة بالشكل الآتي:<syntaxhighlight lang="kotlin"> | |||
==استخدام المجموعات (Collections)== | |||
for (item in items) { | for (item in items) { | ||
println(item) | |||
} | } | ||
</syntaxhighlight>أما للتأكُّد من وجود عنصرٍ ما ضمن المجموعة باستخدام المعامل <code>in</code> | |||
</syntaxhighlight>أما للتأكُّد من وجود عنصرٍ ما ضمن المجموعة باستخدام المعامل <code>in</code> فتصبح الصيغة بالشكل الآتي:<syntaxhighlight lang="kotlin"> | |||
when { | when { | ||
"orange" in items -> println("juicy") | |||
"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) == | |||
==إنشاء الأصناف (Classes) والكائنات الناتجة عنها (Objects)== | |||
يُوضِّح المثال الآتي إنشاء كائنَين من صنفَين مختلفين:<syntaxhighlight lang="kotlin"> | يُوضِّح المثال الآتي إنشاء كائنَين من صنفَين مختلفين:<syntaxhighlight lang="kotlin"> | ||
val rectangle = Rectangle(5.0, 2.0) // لا حاجة | 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]]. | |||
== مصادر == | |||
* [https://kotlinlang.org/docs/reference/basic-syntax.html البنية العامّة في التوثيق الرسميّ للغة Kotlin.] | |||
==مصادر== | |||
* [https://kotlinlang.org/docs/reference/basic-syntax.html | |||
[[تصنيف:Kotlin]] | [[تصنيف: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.