Kotlin: شرح بنية كوتلن الأساسية

آخر تحديث: 2026-08-26

فلسفة بنية كوتلن: استخدم التعبيرات بدلاً من العبارات حيثما أمكن، ولا تكتب سطرًا لا تحتاجه. هذا يتيح لأليس كتابة كود أقصر بنسبة 40% من جافا مع التعبير عن أكثر.

1. ما ستتعلمه


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
قابل لإعادة التعيين لا نعم
أمان الخيوط مرجع ثابت، آمن بطبيعة الحال يحتاج تزامن
التوصية مُفضَّل الملاذ الأخير

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

100%
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 عناصر

📖 ملخص


📝 تمارين

  1. أساسي (⭐) : اكتب دالة باستخدام val وقوالب السلاسل تُخرج ملخص طلب "ORD-001: $299.99 USD (CONFIRMED)". تلميح: val id = "ORD-001"، val total = 299.99
  2. متوسط (⭐⭐) : نفّذ حاسبة خصم مع when: > 10,000 → خصم 20%، > 5,000 → خصم 10%، وإلا السعر الكامل. تلميح: شروط حارس when {}
  3. تحدي (⭐⭐⭐) : نفّذ حاسبة ضغط تصاعدي باستخدام النطاقات وwhen. شرائح دخل مختلفة تطبق معدلات ضرب مختلفة. تلميح: when { income in range -> ... }

← السابق | التالي ←

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%