Kotlin: شرح بنية كوتلن الأساسية
آخر تحديث: 2026-08-26
فلسفة بنية كوتلن: استخدم التعبيرات بدلاً من العبارات حيثما أمكن، ولا تكتب سطرًا لا تحتاجه. هذا يتيح لأليس كتابة كود أقصر بنسبة 40% من جافا مع التعبير عن أكثر.
1. ما ستتعلمه
valمقابلvar: عقلية الثبات أولاً- قوالب السلاسل والسلاسل الخام
- تعبير
whenبجميع أشكاله - النطاقات والتكرار:
../until/step/downTo - دوال جسم التعبير واصطلاحات الكتابة
2. قصة مطور حقيقية
(1) مشكلة: الحالة القابلة للتغيير تسبب أخطاء التزامن
أليس استخدمت var لتعريف عداد طلبات مشترك في OrderProcessor. تحت التزامن العالي، تسببت سباقات البيانات في انحراف عد بنسبة 2% — أي 20,000 طلب خاطئ على نطاق واسع.
(2) حل الثبات أولاً
KOTLIN
// سيئ: حالة مشتركة قابلة للتغيير
var orderCount = 0 // سباق شرطي!
// جيد: ثابت + خط أنابيب وظيفي
val processedOrders = orders
.filter { it.status == "CONFIRMED" }
.also { println("Processed ${it.size} orders") }
البيانات الثابتة آمنة للخيوط بطبيعتها.
valهو الخيار الأول لكل مطور كوتلن؛varهو الملاذ الأخير.
3. val مقابل var: الثبات أولاً
(1) البنية الأساسية
KOTLIN
// val: للقراءة فقط (مرجع ثابت) - مُفضَّل
val orderId = "ORD-001" // نوع مستدل كـ String
val total: Double = 299.99 // نوع صريح
// var: قابل للتغيير (قابل لإعادة التعيين) - استخدم باعتدال
var status = "PENDING" // يمكن إعادة تعيينه
status = "CONFIRMED" // موافق
// val لا يعني أن الكائن ثابت
val items = mutableListOf<Order>() // المرجع val، القائمة قابلة للتغيير
items.add(Order("ORD-002", 150.0, "NEW")) // موافق - تعديل القائمة
// items = mutableListOf() // خطأ - لا يمكن إعادة تعيين val
(2) مقارنة val مقابل var
| البعد | val |
var |
|---|---|---|
| قابل لإعادة التعيين | لا | نعم |
| أمان الخيوط | مرجع ثابت، آمن بطبيعة الحال | يحتاج تزامن |
| التوصية | مُفضَّل | الملاذ الأخير |
- مقابل في جافا |
final| متغير عادي | | تحت الغطاء | مرجع للقراءة فقط (الكائن قد يكون قابلاً للتغيير) | مرجع قابل للتغيير |
4. قوالب السلاسل
(1) القوالب الأساسية
KOTLIN
val orderId = "ORD-001"
val total = 299.99
// إشارة متغيرة بسيطة
println("Order: $orderId")
// تعبير في القالب
println("Total: \$$total USD")
println("Tax: \$${total * 0.08} USD")
// أي تعبير مع ${}
val items = listOf("Widget", "Gadget")
println("Item count: ${items.size}, First: ${items[0]}")
(2) السلاسل الخام (متعددة الأسطر)
KOTLIN
val receipt = """
|Order ID: ORD-001
|Total: $299.99 USD
|Status: CONFIRMED
""".trimMargin()
// بديل: trimIndent
val json = """
{
"order_id": "ORD-001",
"total": 299.99
}
""".trimIndent()
(3) مقارنة قوالب السلاسل
| الميزة | جافا | كوتلن |
|---|---|---|
| إشارة متغيرة | "Order " + id |
"Order $id" |
| تعبير | "Tax: " + (t * 0.08) |
"Tax: ${t * 0.08}" |
| متعدد الأسطر | لا دعم أصلي | """ ... """ |
| معالجة المسافة البادئة | يدوية | trimMargin() / trimIndent() |
5. تعبير when
when هو الترقية الشاملة لـ switch — إنه تعبير بقيمة إرجاع يمكنه مطابقة الأنواع والنطاقات والشروط التعسفية.
(1) الاستخدام الأساسي
KOTLIN
// when كتعبير (يجب أن يكون شاملاً)
val status = "CONFIRMED"
val label = when (status) {
"PENDING" -> "Waiting for payment"
"CONFIRMED" -> "Payment received"
"SHIPPED" -> "In transit"
"CANCELLED" -> "Order cancelled"
else -> "Unknown status"
}
(2) المطابقة المتقدمة
KOTLIN
// قيم متعددة
when (status) {
"PENDING", "NEW" -> processNewOrder()
in listOf("CONFIRMED", "PAID") -> shipOrder()
else -> handleOther()
}
// مطابقة النطاق
val quantity = 150
when (quantity) {
in 1..10 -> println("Small order")
in 11..100 -> println("Medium order")
in 101..1_000 -> println("Large order")
else -> println("Bulk order")
}
// مطابقة النوع
fun describe(obj: Any): String = when (obj) {
is String -> "String of length ${obj.length}"
is Int -> "Integer: $obj"
is List<*> -> "List with ${obj.size} elements"
else -> "Unknown type"
}
(3) شجرة قرارات when
flowchart LR
A[when status] --> B["PENDING, NEW"]
A --> C["CONFIRMED, PAID"]
A --> D["SHIPPED"]
A --> E["CANCELLED"]
A --> F[else]
B --> B1[processNewOrder]
C --> C1[shipOrder]
D --> D1[trackShipment]
E --> E1[refundOrder]
F --> F1[handleOther]
(4) when مقابل switch
| البعد | Java switch | Kotlin when |
|---|---|---|
| قيمة الإرجاع | عبارة، بدون إرجاع | تعبير، يُرجع قيمة |
| مطابقة متعددة القيم | يتطلب fall-through | "A", "B" مفصولة بفواصل |
| مطابقة النطاق | غير متوفرة | in 1..100 |
| مطابقة النوع | غير متوفرة | is String |
| شرط حارس | غير متوفرة | x > 0 تعسفي |
| فحص الشمول | لا شيء | مفروض من المُترجِم (وضع التعبير) |
6. النطاقات والتكرار
(1) عوامل النطاق
KOTLIN
// نطاق مغلق: يشمل كلا الطرفين
for (i in 1..5) print("$i ") // 1 2 3 4 5
// نطاق نصف مفتوح: يستبعد الطرف
for (i in 1 until 5) print("$i ") // 1 2 3 4
// خطوة
for (i in 1..10 step 2) print("$i ") // 1 3 5 7 9
// تنازلي
for (i in 5 downTo 1) print("$i ") // 5 4 3 2 1
// نطاق أحرف
for (c in 'A'..'E') print("$c ") // A B C D E
(2) تكرار المجموعات
KOTLIN
val orders = listOf(
Order("ORD-001", 299.99),
Order("ORD-002", 1_500.00),
Order("ORD-003", 45.50)
)
// تكرار مع فهرس
for ((index, order) in orders.withIndex()) {
println("[$index] ${order.id}: \$${order.total} USD")
}
// تكرار الخريطة
val statusMap = mapOf("ORD-001" to "SHIPPED", "ORD-002" to "PENDING")
for ((id, status) in statusMap) {
println("$id -> $status")
}
(3) مرجع سريع لعوامل النطاق
| العامل | المعنى | مثال | النتيجة |
|---|---|---|---|
.. |
نطاق مغلق | 1..5 |
1,2,3,4,5 |
until |
نطاق نصف مفتوح | 1 until 5 |
1,2,3,4 |
step |
حجم الخطوة | 1..10 step 3 |
1,4,7,10 |
downTo |
تنازلي | 5 downTo 1 |
5,4,3,2,1 |
in |
فحص العضوية | 3 in 1..5 |
true |
7. دوال جسم التعبير والاصطلاحات
(1) دوال جسم التعبير
KOTLIN
// جسم كتلة
fun calculateTax(total: Double): Double {
return total * 0.08
}
// جسم تعبير (أكثر إيجازًا)
fun calculateTax(total: Double): Double = total * 0.08
// استدلال النوع مع جسم التعبير
fun calculateTax(total: Double) = total * 0.08
(2) اصطلاحات كوتلن
KOTLIN
// 1. الفواصل المنقوطة اختيارية
val x = 1 // لا حاجة لفاصلة منقوطة
// 2. اصطلاح lambda الخلفي
orders.filter { it.total > 1_000 } // lambda خارج الأقواس
// 3. كلمة it لـ lambda ذات المعامل الواحد
orders.map { it.id } // 'it' = معامل ضمني
// 4. قالب سلسلة بدلاً من الوصل
val msg = "Order $orderId confirmed" // ليس "Order " + orderId + " confirmed"
// 5. جسم تعبير للدوال البسيطة
fun isHighValue(order: Order) = order.total > 10_000
(3) مقارنة اصطلاحات جافا مقابل كوتلن
| الاصطلاح | جافا | كوتلن |
|---|---|---|
| الفواصل المنقوطة | مطلوبة | اختيارية |
| وصل السلاسل | عامل + |
قالب $ |
| الدوال البسيطة | جسم كتلة | جسم تعبير |
| موضع lambda | داخل الأقواس | خلفية خارج الأقواس |
| lambda ذات معامل واحد | معامل مسمى | كلمة it |
8. مثال كامل: توجيه طلبات OrderProcessor
KOTLIN
// ============================================
// OrderProcessor - محرك توجيه الطلبات
// الميزة: توجيه الطلبات بناءً على الحالة والقيمة
// ============================================
data class Order(val id: String, val total: Double, val status: String)
fun routeOrder(order: Order): String = when {
order.status == "CANCELLED" -> "REFUND_QUEUE"
order.total > 10_000 -> "VIP_PIPELINE"
order.total > 1_000 -> "PRIORITY_PIPELINE"
order.status == "CONFIRMED" -> "STANDARD_PIPELINE"
order.status in listOf("PENDING", "NEW") -> "WAITING_QUEUE"
else -> "MANUAL_REVIEW"
}
fun processBatch(orders: List<Order>) {
for ((index, order) in orders.withIndex()) {
val pipeline = routeOrder(order)
val priority = when (pipeline) {
"VIP_PIPELINE" -> "CRITICAL"
"PRIORITY_PIPELINE" -> "HIGH"
"STANDARD_PIPELINE" -> "NORMAL"
else -> "LOW"
}
println("[${index + 1}] ${order.id} -> $pipeline (Priority: $priority)")
}
}
fun main() {
val orders = listOf(
Order("ORD-001", 299.99, "CONFIRMED"),
Order("ORD-002", 15_000.00, "CONFIRMED"),
Order("ORD-003", 2_500.00, "PENDING"),
Order("ORD-004", 45.50, "CANCELLED"),
Order("ORD-005", 750.00, "NEW")
)
println("=== Order Routing Report ===")
processBatch(orders)
// ملخص مع خط أنابيب وظيفي
val pipelineCounts = orders
.map { routeOrder(it) }
.groupingBy { it }
.eachCount()
println("\n=== Pipeline Distribution ===")
for ((pipeline, count) in pipelineCounts) {
println(" $pipeline: $count orders")
}
}
المخرجات:
TEXT
📖 للعرض فقط
=== Order Routing Report ===
[1] ORD-001 -> STANDARD_PIPELINE (Priority: NORMAL)
[2] ORD-002 -> VIP_PIPELINE (Priority: CRITICAL)
[3] ORD-003 -> PRIORITY_PIPELINE (Priority: HIGH)
[4] ORD-004 -> REFUND_QUEUE (Priority: LOW)
[5] ORD-005 -> WAITING_QUEUE (Priority: LOW)
=== Pipeline Distribution ===
STANDARD_PIPELINE: 1 orders
VIP_PIPELINE: 1 orders
PRIORITY_PIPELINE: 1 orders
REFUND_QUEUE: 1 orders
WAITING_QUEUE: 1 orders
❓ أسئلة شائعة
س هل يمكنني تعديل محتويات مجموعة val؟
ج نعم. val يضمن فقط أن المرجع ثابت — محتويات المجموعة يمكن أن تتغير. لمجموعات ثابتة حقًا، استخدم
listOf() بدلاً من mutableListOf().س هل يحتاج when دائمًا إلى else؟
ج عندما يُستخدم
when كتعبير، يطلب المُترجِم الشمول — يجب أن تغطي جميع الفروع أو تضيف else. عند استخدامه كعبارة، else اختياري.س هل
1..5 و1 until 6 متماثلان؟ج نفس النتيجة، دلالات مختلفة.
1..5 يعني "من 1 إلى 5 شاملاً"، 1 until 6 يعني "من 1 حتى (ولكن لا يشمل) 6". عند تكرار فهارس القوائم، until أكثر شيوعًا.س متى يجب أن أستخدم دوال جسم التعبير؟
ج استخدم أجسام التعبير عندما تكون الدالة تعبيرًا واحدًا. استخدم أجسام الكتل لأي شيء به 2+ سطر من المنطق. القراءة هي الأولوية القصوى.
س ما الفرق بين
$var و${expr} في قوالب السلاسل؟ج
$var يمكنه فقط الإشارة لأسماء المتغيرات البسيطة؛ ${expr} يمكنه احتواء أي تعبير، مثل ${items.size} أو ${total * 0.08}.س هل يمكن لـ when مطابقة نطاقات الفاصلة العائمة؟
ج تقنيًا نعم، لكن مشاكل دقة الفاصلة العائمة قد تسبب نتائج غير متوقعة. فضّل النطاقات الصحيحة أو المقارنات الصريحة.
▶ مثال: val مقابل var
KOTLIN
val name = "Alice" // ثابت
var age = 30 // قابل للتغيير
age = 31 // موافق
// name = "Bob" // خطأ ترجمة
المخرجات:
TEXT
📖 للعرض فقط
يُترجَل؛ إعادة تعيين name تفشل
▶ مثال: تعبير when
KOTLIN
val score = 85
val grade = when {
score >= 90 -> "A"
score >= 80 -> "B"
else -> "C"
}
println(grade)
المخرجات:
TEXT
📖 للعرض فقط
B
▶ مثال: حلقة for
KOTLIN
for (i in 1..3) println(i)
for (s in listOf("a", "b")) println(s)
المخرجات:
TEXT
📖 للعرض فقط
1
2
3
a
b
▶ مثال: قالب سلسلة متعدد الأسطر
KOTLIN
val name = "Alice"
val orders = 1500
val revenue = 89500.50
val summary = """
|== تقرير المستخدم ==
| الاسم : $name
| الطلبات : $orders
| الإيراد : \$${revenue} USD
| المتوسط : \$${revenue / orders} USD
|================
""".trimMargin()
println(summary)
**المخرجات:
TEXT
📖 للعرض فقط
|== تقرير المستخدم ==
| الاسم : Alice
| الطلبات : 1500
| الإيراد : $89500.5 USD
| المتوسط : $59.66699999999999 USD
|================
▶ مثال: نطاق مع step و downTo
KOTLIN
// نطاق تصاعدي مع step
for (i in 1..10 step 2) print("$i ")
println()
// نطاق تنازلي
for (i in 5 downTo 1) print("$i ")
println()
// نصف مفتوح مع until
for (i in 0 until 5) print("$i ")
**المخرجات:
TEXT
📖 للعرض فقط
1 3 5 7 9
5 4 3 2 1
0 1 2 3 4
▶ مثال: دالة جسم التعبير
KOTLIN
// جسم كتلة — متعدد الأسطر
fun describeOrder(status: String): String {
return when (status) {
"CONFIRMED" -> "تم التأكيد"
"SHIPPED" -> "تم الشحن"
"DELIVERED" -> "تم التسليم"
"CANCELLED" -> "ملغي"
else -> "غير معروف"
}
}
// جسم تعبير — سطر واحد
fun isVip(total: Double) = total > 10_000
// دالة بدون قيمة مرجعة (Unit)
fun logOrder(id: String): Unit = println("Logged: $id")
println(describeOrder("CONFIRMED"))
println("VIP: ${isVip(15_000.0)}")
logOrder("ORD-001")
**المخرجات:
TEXT
📖 للعرض فقط
تم التأكيد
VIP: true
Logged: ORD-001
▶ مثال: Null safety مع when
KOTLIN
fun describeValue(v: Any?): String = when (v) {
null -> "القيمة فارغة"
is String -> "نص بطول ${v.length}: $v"
is Int -> if (v > 0) "عدد موجب" else "عدد غير موجب"
is List<*> -> "قائمة بـ ${v.size} عناصر"
else -> "نوع غير معروف: ${v::class.simpleName}"
}
println(describeValue(null))
println(describeValue("مرحبا"))
println(describeValue(42))
println(describeValue(listOf(1, 2, 3)))
**المخرجات:
TEXT
📖 للعرض فقط
القيمة فارغة
نص بطول 6: مرحبا
عدد موجب
قائمة بـ 3 عناصر
📖 ملخص
valأولاً،varأخيرًا — المراجع الثابتة آمنة للخيوط بطبيعتها- قوالب السلاسل مع
$/${}تحل محل وصل السلاسل؛"""للأسطر المتعددة whenهو الترقية التعبيرية لـswitch: مطابقة متعددة القيم، النطاقات، الأنواع، وشروط الحارس- عوامل النطاق:
..(مغلق)،until(نصف مفتوح)،step،downTo - دوال جسم التعبير تجعل الدوال البسيطة موجزة؛ القراءة تحدد المفاضلة
- اصطلاحات كوتلن: بدون فواصل منقوطة، lambda خلفية، كلمة
it، قوالب السلاسل
📝 تمارين
- أساسي (⭐) : اكتب دالة باستخدام
valوقوالب السلاسل تُخرج ملخص طلب"ORD-001: $299.99 USD (CONFIRMED)". تلميح:val id = "ORD-001"،val total = 299.99 - متوسط (⭐⭐) : نفّذ حاسبة خصم مع
when: > 10,000 → خصم 20%، > 5,000 → خصم 10%، وإلا السعر الكامل. تلميح: شروط حارسwhen {} - تحدي (⭐⭐⭐) : نفّذ حاسبة ضغط تصاعدي باستخدام النطاقات و
when. شرائح دخل مختلفة تطبق معدلات ضرب مختلفة. تلميح:when { income in range -> ... }