ورقة غش Kotlin
آخر تحديث
Hello World والأساسيات
يبدأ برنامج Kotlin من دالة main في المستوى الأعلى، دون الحاجة إلى فئة.
| الصياغة | المعنى |
|---|---|
fun main() { println("Hello") } | نقطة دخول البرنامج |
println("text") | طباعة سطر إلى المخرجات القياسية |
print("text") | طباعة دون سطر جديد في النهاية |
// comment | تعليق من سطر واحد |
/* comment */ | تعليق متعدد الأسطر |
val input = readLine() | قراءة سطر من stdin (String? قابل للفراغ) |
val line = readln() | قراءة سطر من stdin (غير فارغ، Kotlin 1.6+) |
المتغيرات (val / var) والأنواع
فضّل val؛ ولا تلجأ إلى var إلا عندما يجب أن تتغير القيمة.
| الصياغة | المعنى |
|---|---|
val name = "Ada" | متغير للقراءة فقط، يُستنتج نوعه String |
var count = 0 | متغير قابل للتغيير |
val age: Int = 30 | تحديد النوع صراحةً |
Int, Long, Double, Float | الأنواع الرقمية (42, 42L, 3.14, 3.14f) |
Boolean, Char, String | true/false, 'a', "text" |
val big = 1_000_000 | شرطات سفلية لقيم حرفية مقروءة |
"3".toInt(), "2.5".toDouble() | تحويل نص إلى رقم |
42.toString() | رقم إلى نص |
const val MAX = 10 | ثابت وقت الترجمة (في المستوى الأعلى أو داخل object) |
النصوص والقوالب
قوالب النصوص تحل محل الضم في كل مكان تقريبًا.
| الصياغة | المعنى |
|---|---|
"Hi, $name" | إدراج متغير في نص |
"Total: ${price * qty}" | إدراج تعبير |
s.length | عدد الأحرف |
s.uppercase(), s.lowercase() | تغيير حالة الأحرف |
s.trim() | إزالة المسافات من البداية والنهاية |
s.contains("x"), s.startsWith("a") | البحث داخل نص |
s.substring(0, 3) | اقتطاع بنطاق فهارس |
s.split(",") | تقسيم إلى List<String> |
s[0] | الحرف عند فهرس معين |
"""raw text""" | نص خام متعدد الأسطر دون هروب |
"%.2f".format(3.14159) | ناتج منسّق (3.14) |
أمان القيم الفارغة
النوع غير قابل للفراغ افتراضيًا؛ أضف ? للسماح بـ null، وسيجبرك المترجم على معالجته.
| الصياغة | المعنى |
|---|---|
var s: String? = null | نوع قابل للفراغ |
s?.length | استدعاء آمن: يعيد null إذا كان s هو null |
s?.length ?: 0 | عامل Elvis: قيمة بديلة عند null |
s!!.length | تأكيد عدم الفراغ: يرمي استثناءً إذا كان s هو null |
if (s != null) s.length | تحويل ذكي إلى غير فارغ داخل الفحص |
s?.let { println(it) } | تنفيذ كتلة فقط عندما لا تكون null |
val n = s?.toIntOrNull() | تحويل، أو null عند إدخال غير صالح |
lateinit var x: String | متغير غير فارغ يُهيّأ لاحقًا |
العوامل
| العامل | المعنى |
|---|---|
+ - * / % | حسابية (/ بين قيم Int قسمة صحيحة) |
+= -= *= /= %= | إسناد مركّب |
++ -- | زيادة / إنقاص |
== != | مساواة بنيوية (تستدعي equals) |
=== !== | مساواة مرجعية (الكائن نفسه) |
< > <= >= | مقارنة |
&& || ! | و / أو / نفي منطقية |
a in 1..10 | الانتماء إلى نطاق أو مجموعة |
x as Int, x as? Int | تحويل / تحويل آمن (null عند الفشل) |
x is String | فحص النوع (تحويل ذكي عند النجاح) |
التحكم في التدفق (if / when)
if و when تعبيران يعيدان قيمة.
| الصياغة | المعنى |
|---|---|
if (a > b) x else y | if كتعبير (لا يوجد في Kotlin عامل ثلاثي ?:) |
if (c) { ... } else if (d) { ... } else { ... } | فروع متسلسلة |
when (x) { 1 -> "one"; 2 -> "two"; else -> "other" } | مطابقة قيمة |
when (x) { 1, 2 -> "low" } | عدة قيم في فرع واحد |
when (x) { in 1..9 -> "digit" } | مطابقة نطاق |
when (x) { is String -> x.length } | مطابقة نوع (مع تحويل ذكي) |
when { x < 0 -> "neg"; x == 0 -> "zero"; else -> "pos" } | when بدون موضوع، مثل if/else if |
val label = when (x) { ... } | when كتعبير (يحتاج else) |
الحلقات والنطاقات
| الصياغة | المعنى |
|---|---|
for (i in 1..5) | نطاق شامل من 1 إلى 5 |
for (i in 1 until 5) | من 1 إلى 4 (النهاية غير مشمولة) |
for (i in 0..<5) | الشيء نفسه بصياغة النطاق المفتوح (Kotlin 1.9+) |
for (i in 10 downTo 1 step 2) | العد التنازلي بخطوات |
for (item in list) | المرور على مجموعة |
for ((i, item) in list.withIndex()) | الفهرس والعنصر معًا |
for (ch in "abc") | المرور على أحرف نص |
while (cond) { ... } | تكرار ما دام الشرط صحيحًا |
do { ... } while (cond) | التنفيذ مرة واحدة على الأقل |
break, continue | الخروج من الحلقة / الانتقال إلى التكرار التالي |
repeat(3) { println(it) } | تنفيذ كتلة n مرة |
الدوال
| الصياغة | المعنى |
|---|---|
fun add(a: Int, b: Int): Int { return a + b } | تعريف دالة |
fun add(a: Int, b: Int) = a + b | دالة بتعبير واحد، نوع الإرجاع مستنتج |
fun greet(name: String = "world") | قيمة افتراضية لمعامل |
greet(name = "Ada") | وسيط مسمّى |
fun log(vararg items: String) | عدد متغير من الوسائط |
fun say(): Unit | بدون قيمة إرجاع (Unit اختياري) |
val square = { x: Int -> x * x } | لامدا مخزنة في متغير |
fun String.shout() = uppercase() + "!" | دالة امتداد |
fun apply(f: (Int) -> Int) = f(2) | دالة كمعامل |
list.map { it * 2 } | لامدا لاحقة، it هو المعامل الوحيد |
القوائم
listOf للقراءة فقط؛ mutableListOf قابلة للتغيير.
| الصياغة | المعنى |
|---|---|
val nums = listOf(1, 2, 3) | قائمة للقراءة فقط |
val items = mutableListOf("a") | قائمة قابلة للتغيير |
nums[0], nums.first(), nums.last() | الوصول إلى العناصر |
nums.getOrNull(9) | وصول آمن، null خارج النطاق |
items.add("b"), items.remove("a") | إضافة / إزالة |
items[0] = "z" | استبدال بالفهرس |
nums.size, nums.isEmpty() | الحجم وهل هي فارغة |
x in nums, nums.contains(x) | الانتماء |
nums.indexOf(2) | موضع عنصر، -1 إن لم يوجد |
nums.subList(0, 2) | قائمة فرعية (النهاية غير مشمولة) |
nums.take(2), nums.drop(1) | أول n / الكل عدا أول n |
nums.sorted(), nums.reversed() | قائمة جديدة مرتبة / معكوسة |
nums.sum(), nums.average(), nums.maxOrNull() | تجميعات |
nums.joinToString(", ") | الدمج في نص واحد |
Pair(1, "a"), 1 to "a", Triple(1, 2, 3) | صفوف صغيرة ثابتة الحجم |
الخرائط والمجموعات
| الصياغة | المعنى |
|---|---|
val m = mapOf("a" to 1, "b" to 2) | خريطة للقراءة فقط |
val mm = mutableMapOf<String, Int>() | خريطة قابلة للتغيير |
m["a"] | بحث (null إن لم يوجد) |
m.getOrDefault("z", 0) | بحث مع قيمة بديلة |
mm["c"] = 3 | إدراج أو تحديث |
for ((k, v) in m) | المرور على المدخلات بالتفكيك |
m.keys, m.values | مجموعتا المفاتيح / القيم |
"a" in m | وجود مفتاح |
val s = setOf(1, 2, 2) | مجموعة قيم فريدة ({1, 2}) |
mutableSetOf<Int>() | مجموعة قابلة للتغيير |
عمليات المجموعات (لامدا)
| الصياغة | المعنى |
|---|---|
list.map { it * 2 } | تحويل كل عنصر |
list.filter { it > 2 } | الإبقاء على العناصر المطابقة |
list.forEach { println(it) } | تنفيذ شيء مع كل عنصر |
list.any { it > 2 }, list.all { it > 0 } | هل يطابق أي / كل عنصر |
list.count { it % 2 == 0 } | عدّ المطابقات |
list.find { it > 2 } | أول مطابقة أو null |
list.sortedBy { it.length } | الترتيب بمفتاح |
list.groupBy { it.first() } | التجميع في Map |
list.distinct() | إزالة التكرارات |
list.fold(0) { acc, x -> acc + x } | الاختزال بقيمة ابتدائية |
list.zip(other) | إقران قائمتين |
list.flatMap { it.toList() } | تحويل ثم تسطيح |
الفئات وفئات البيانات
| الصياغة | المعنى |
|---|---|
class User(val name: String, var age: Int) | فئة بمنشئ أساسي وخصائص |
val u = User("Ada", 36) | إنشاء نسخة (بدون new) |
u.name, u.age = 37 | قراءة / كتابة الخصائص |
data class Point(val x: Int, val y: Int) | equals, hashCode, toString, copy مجانًا |
p.copy(y = 5) | نسخة مع تغيير بعض الخصائص |
val (x, y) = p | تصريح تفكيك |
open class Base, class Sub : Base() | الوراثة (الفئات final افتراضيًا) |
override fun toString() = "..." | تجاوز عضو |
object Config { val debug = true } | كائن مفرد |
companion object { fun create() = User("", 0) } | أعضاء شبه ثابتة |
enum class Color { RED, GREEN } | تعداد |
sealed class Result | تسلسل فئات مقيّد، شامل في when |
interface Shape { fun area(): Double } | واجهة |
معالجة الأخطاء
| الصياغة | المعنى |
|---|---|
try { ... } catch (e: Exception) { ... } | التقاط استثناء |
try { ... } finally { ... } | تنفيذ التنظيف دائمًا |
val n = try { s.toInt() } catch (e: NumberFormatException) { 0 } | try كتعبير |
throw IllegalArgumentException("bad") | رمي استثناء |
require(x > 0) { "x must be positive" } | فحص الوسيط (يرمي IllegalArgumentException) |
check(ready) { "not ready" } | فحص الحالة (يرمي IllegalStateException) |
s.toIntOrNull() | إرجاع null بدلًا من الرمي |
runCatching { risky() }.getOrDefault(0) | تغليف استدعاء في Result |
دوال النطاق
خمسة مساعدات صغيرة للعمل مع كائن داخل كتلة.
| الصياغة | المعنى |
|---|---|
x.let { it + 1 } | it هو الكائن، يعيد نتيجة الكتلة |
x.run { this + 1 } | this هو الكائن، يعيد نتيجة الكتلة |
x.apply { field = 1 } | this هو الكائن، يعيد الكائن |
x.also { println(it) } | it هو الكائن، يعيد الكائن |
with(x) { field } | ليست امتدادًا؛ this هو x، تعيد نتيجة الكتلة |
x?.let { ... } | فحص الفراغ الاصطلاحي + الاستخدام |
كل صياغة Kotlin التي تبحث عنها في صفحة واحدة. ورقة غش Kotlin هذه مرجع سريع للغة التي تقف خلف أندرويد وجزء كبير من JVM الحديثة: تعريف المتغيرات، التعامل الآمن مع القيم الفارغة، التفريع بـ when، المرور على النطاقات، كتابة الدوال، والعمل مع القوائم والخرائط.
كل ما هنا هو Kotlin قياسي يعمل بالطريقة نفسها على JVM وأندرويد و Kotlin Multiplatform. انسخ ما تحتاجه، أو جرّبه مباشرة في ملعب Kotlin: الصق مقطعًا، اضغط Run، وشاهد الناتج في متصفحك.
الأسئلة الشائعة حول ورقة غش Kotlin
هل ورقة غش Kotlin هذه مجانية؟
when أو عامل أمان القيم الفارغة أو دالة من دوال المجموعات.ما الفرق بين val و var في Kotlin؟
val يعرّف مرجعًا للقراءة فقط: يُسند مرة واحدة ولا يمكن إعادة إسناده. var يعرّف متغيرًا قابلًا للتغيير يمكن إعادة إسناده. لاحظ أن val يثبّت المرجع فقط، فـ val list = mutableListOf(1) ما زال يمكن إضافة عناصر إليها. أسلوب Kotlin هو استخدام val في كل مكان والتحول إلى var فقط عندما تكون إعادة الإسناد ضرورية فعلًا.كيف يعمل أمان القيم الفارغة في Kotlin؟
String القيمة null أبدًا، بينما String? يمكنه ذلك. لا يسمح لك المترجم باستدعاء دالة على قيمة قابلة للفراغ دون معالجة حالة null: باستدعاء آمن (s?.length)، أو قيمة بديلة بعامل Elvis (s?.length ?: 0)، أو فحص للفراغ مع تحويل ذكي (if (s != null))، أو كملاذ أخير تأكيد عدم الفراغ s!! الذي يرمي NullPointerException إذا كانت القيمة null فعلًا.متى أستخدم when بدلًا من if في Kotlin؟
when كلما قارنت قيمة واحدة بعدة احتمالات - ثوابت أو نطاقات أو أنواع أو مزيج منها - واستخدم if/else لشرط واحد بنعم أو لا. كلاهما تعبير، لذا فإن val label = when (x) { ... } و val label = if (c) a else b اصطلاحيان. يجب أن يكون when المستخدم كتعبير شاملًا، وهو ما يعني عادةً إضافة فرع else (فئات sealed والتعدادات يمكن أن تكون شاملة بدونه).هل يمكنني التدرب على Kotlin عبر الإنترنت؟
when والحلقات والدوال والمجموعات، ويمنحك شهادة مجانية في النهاية.