Kotlin: مقدمة في كوتلن وفلسفة التصميم

كوتلن هو "جافا الأفضل" من JetBrains — يعيد تشكيل تجربة تطوير JVM بتركيب أنظف وأكثر أمانًا مع الحفاظ على توافق بنسبة 100% مع جافا.

1. ما ستتعلمه


2. قصة مهندس معمارية حقيقية

(1) مشكلة: كود جافا الزائد يستنزف الإنتاجية

تشارلي هو قائد تقني في شركة تجارة إلكترونية، مسؤول عن خدمة OrderProcessor المصغرة. فريقه يكتب جافا ويصارع الكود الزائد كل يوم:

JAVA
// Java: 20+ سطر فقط لتعريف POJO بسيط
public class Order {
    private String id;
    private BigDecimal total;
    private String status;

    public Order(String id, BigDecimal total, String status) {
        this.id = id;
        this.total = total;
        this.status = status;
    }

    public String getId() { return id; }
    public BigDecimal getTotal() { return total; }
    public String getStatus() { return status; }

    @Override
    public boolean equals(Object o) { /* 10+ أسطر */ }
    @Override
    public int hashCode() { /* 5+ أسطر */ }
    @Override
    public String toString() { /* 3+ أسطر */ }
}

كل فئة كيان جديدة تكلف تشارلي 60+ سطرًا من الكود الزائد. NullPointerException يسبب 15+ حادث إنتاج شهريًا.

(2) حل كوتلن

KOTLIN
// Kotlin: سطر واحد يفعل كل شيء
data class Order(val id: String, val total: BigDecimal, val status: String)

سطر واحد من كوتلن يحل محل 60+ سطر من كود جافا الزائد. نظام الأنواع الآمن للفارغ يقضي على NPE في وقت الترجمة.


3. ميلاد كوتلن وفلسفة التصميم

أطلقت JetBrains مشروع كوتلن في عام 2010 بهدف واحد: إنشاء "جافا أفضل" — ليس لاستبدال جافا، بل لجعل مطوري منظومة جافا أكثر إنتاجية وأمانًا.

(1) مبادئ التصميم الأساسية

(2) مقارنة تصميم كوتلن مقابل جافا

البعد جافا كوتلن
أمان الفارغ NPE في وقت التشغيل أنواع فارغة في وقت الترجمة ?
فئات البيانات getter/equals/hashCode يدوي data class مُولَّد تلقائيًا
البرمجة الوظيفية Stream API (مطوّل) سلسلة map/filter
Coroutines لا دعم أصلي suspend + التزامن المنظم
دوال الامتداد غير متوفرة fun Type.extension()
المعلمات الافتراضية تحميل الطرق fun foo(x: Int = 0)
التحويل الذكي تحويل نوع يدوي تحويل تلقائي بـ is

4. الحمض النووي متعدد المنصات

كوتلن ليس مجرد لغة JVM — إنه متعدد المنصات بالتصميم.

100%
mindmap
  root((Kotlin Ecosystem))
    JVM
      Spring Boot
      Android
      Ktor
    Native
      iOS
      macOS
      Linux
    JS
      Node.js
      Browser
    Wasm
      Web Assembly
    Shared
      kotlinx.coroutines
      kotlinx.serialization
      KMP common code

(1) تموضع المنصات

المنصة حالة الاستخدام هدف الترجمة
JVM خدمات الخلفية، تطبيقات المؤسسات .class / .jar
Android تطبيقات الهاتف DEX (ART)
Native iOS، الأنظمة المدمجة، الأداء العالي Native binary
JS واجهة الويب الأمامية .js / .wasm
Wasm الحسابات عالية الأداء في المتصفح .wasm

(2) استراتيجية مشاركة الكود متعدد المنصات

KOTLIN
// commonMain - مشترك عبر جميع المنصات
expect fun logMessage(message: String)

// منصة JVM
actual fun logMessage(message: String) = println("[JVM] $message")

// منصة JS
actual fun logMessage(message: String) = console.log("[JS] $message")

5. فلسفة تصميم أمان الفارغ

أكثر تصميم ثوري في كوتلن: null ينتمي لنظام الأنواع، وليس لغماً في وقت التشغيل.

(1) الأنواع الفارغة وغير الفارغة

KOTLIN
// نوع غير فارغ: لا يمكن أن يكون null
val orderId: String = "ORD-001"

// نوع فارغ: يجب استخدام اللاحقة ?
val customerName: String? = null

// عامل الاستدعاء الآمن
val length = customerName?.length  // null إذا كان customerName فارغًا

// عامل Elvis: توفير قيمة افتراضية
val name = customerName ?: "Unknown"

// تأكيد عدم الفارغ: رمي NPE إذا كان فارغًا (استخدم باعتدال)
val forced = customerName!!

(2) مقارنة عوامل أمان الفارغ

العامل الاسم السلوك حالة الاستخدام
?. استدعاء آمن يُرجع null عند null الوصول المتسلسل للخصائص
?: Elvis يُرجع القيمة الافتراضية عند null توفير قيمة بديلة
!! تأكيد عدم الفارغ يرمي NPE عند null عند التأكد من عدم الفارغ
?.let { } سلسلة let تخطي التنفيذ عند null تنفيذ كتلة شرطية

6. نظرة عامة على المنظومة

(1) المكتبات والأطر الأساسية

الطبقة المشروع الممثل الغرض
غير متزامن kotlinx.coroutines Coroutines والتزامن المنظم
تدفق kotlinx.coroutines Flow خطوط بيانات التدفق البارد
التسلسل kotlinx.serialization JSON / ProtoBuf في وقت الترجمة
خلفية الويب Spring Boot / Ktor تطوير الخدمات المصغرة
واجهة المستخدم Jetpack Compose / Compose Multiplatform واجهة مستخدم تصريحية
متعدد المنصات KMP مشاركة الكود عبر المنصات

(2) حزمة تقنيات OrderProcessor لتشارلي

100%
graph LR
    A[OrderProcessor<br/>Kotlin Microservice] --> B[Spring Boot<br/>REST API]
    A --> C[Coroutines<br/>Async Processing]
    A --> D[kotlinx.serialization<br/>JSON Codec]
    A --> E[R2DBC<br/>Reactive DB]
    A --> F[Ktor Client<br/>HTTP Calls]

7. مثال كامل: أول برنامج كوتلن لتشارلي

KOTLIN
// ============================================
// OrderProcessor - أول برنامج كوتلن
// الميزة: تعريف نموذج الطلب وطباعة الملخص
// ============================================

// فئة بيانات: توليد تلقائي لـ equals/hashCode/toString/copy
data class Order(val id: String, val total: Double, val status: String)

data class Customer(val name: String, val email: String?)

fun main() {
    // إنشاء الطلبات
    val order1 = Order("ORD-001", 299.99, "SHIPPED")
    val order2 = Order("ORD-002", 1_500.00, "PROCESSING")

    // عميل فارغ
    val customer: Customer? = Customer("Alice", "alice@example.com")

    // استدعاء آمن + عامل Elvis
    val email = customer?.email ?: "no-email"

    // قالب سلسلة
    println("Order: ${order1.id}, Total: \$${order1.total} USD, Status: ${order1.status}")
    println("Customer email: $email")

    // تعبير when (مثل switch لكن أقوى)
    val priority = when {
        order2.total > 1_000 -> "HIGH"
        order2.total > 500 -> "MEDIUM"
        else -> "LOW"
    }
    println("Order ${order2.id} priority: $priority")

    // تحويل ذكي
    val result: Any = order1
    if (result is Order) {
        // لا حاجة لتحويل صريح!
        println("Smart cast: ${result.id} - ${result.total} USD")
    }
}

المخرجات:

TEXT 📖 للعرض فقط
Order: ORD-001, Total: $299.99 USD, Status: SHIPPED
Customer email: alice@example.com
Order ORD-002 priority: HIGH
Smart cast: ORD-001 - 299.99 USD

8. أمثلة عملية سريعة

▶ مثال: عوامل الحساب والمقارنة

يوضح كوتلن عوامل حسابية ومقارنة مختصرة الميزة الرئيسية: لا يوجد ترقية رقمية ضمنية — يجب استدعاء .toInt() صراحةً.

KOTLIN
// ============================================
// العوامل الأساسية — لا يوجد تحويل ضمني بين الأعداد
// الميزة: استدعاء صريح لـ toInt/toDouble
// ============================================

val intVal: Int = 42
val longVal: Long = 42L
val doubleVal: Double = 3.14
val boolVal: Boolean = true

// عامل حسابي
val sum = intVal + 100           // 142 (Int)
val product = intVal * 2          // 84

// مقارنة — تُرجع Boolean
val isPositive = intVal > 0       // true
val isEqual = intVal == 42L       // false! Int != Long

// تحويل صريح مطلوب
val widened = intVal.toLong()      // 42L
val narrowed = doubleVal.toInt()   // 3 (اقتطاع)

// استخدام في if/when
val category = when {
    intVal < 10 -> "small"
    intVal < 100 -> "medium"
    else -> "large"
}

println("sum=$sum, product=$product, isPositive=$isPositive, category=$category")

المخرجات:

TEXT 📖 للعرض فقط
sum=142, product=84, isPositive=true, category=medium

▶ مثال: القوائم وعمليات التحصيل

تعرض كوتلن واجهة بديهية للقوائم مع دعم forEach/map/filter كدوال امتداد.

KOTLIN
// ============================================
// قوائم كوتلن — forEach/map/filter بسلسلة
// الميزة: البرمجة الوظيفية مدمجة في اللغة
// ============================================

val orders = listOf(
    "ORD-001" to 299.99,
    "ORD-002" to 1500.00,
    "ORD-003" to 50.00,
    "ORD-004" to 3200.00
)

// forEach — استدعاء على كل عنصر
println("=== جميع الطلبات ===")
orders.forEach { (id, total) ->
    println("$id: \$$total USD")
}

// map — تحويل كل عنصر
val totals = orders.map { it.second }
println("Totals: $totals")

// filter — تصفية حسب شرط
val highValue = orders.filter { it.second > 500.0 }
println("طلبات عالية القيمة: ${highValue.size}")

// sum — مجموع القيم (دالة امتداد على Iterable)
val grandTotal = totals.sum()
println("Grand total: \$${grandTotal} USD")

المخرجات:

TEXT 📖 للعرض فقط
=== جميع الطلبات ===
ORD-001: $299.99 USD
ORD-002: $1500.0 USD
ORD-003: $50.0 USD
ORD-004: $3200.0 USD
Totals: [299.99, 1500.0, 50.0, 3200.0]
طلبات عالية القيمة: 2
Grand total: $5049.99 USD

▶ مثال: تعبير when متعدد الفروع

يعد تعبير when أقوى من switch — يدعم مطابقة النمط والقيم والشروط.

KOTLIN
// ============================================
// تعبير when — بديل قوي لـ switch
// الميزة: يدعم مطابقة النوع، النطاق، والقيمة
// ============================================

fun describeOrder(order: Any): String = when (order) {
    is String -> "معرف طلب: $order"
    is Int -> "عدد صحيح: $order"
    is List<*> -> "قائمة بـ ${order.size} عناصر"
    in 1..10 -> "رقم في النطاق 1-10: $order"
    "special" -> "قيمة خاصة"
    else -> "نوع غير معروف"
}

println(describeOrder("ORD-001"))
println(describeOrder(42))
println(describeOrder(listOf(1, 2, 3)))
println(describeOrder(7))
println(describeOrder("special"))
println(describeOrder(3.14))

المخرجات:

TEXT 📖 للعرض فقط
معرف طلب: ORD-001
عدد صحيح: 42
قائمة بـ 3 عناصر
رقم في النطاق 1-10: 7
قيمة خاصة
نوع غير معروف

▶ مثال: Hello World

أبسط برنامج كوتلن — برنامج main وحيد مع println.

KOTLIN
fun main() {
    println("Hello, Kotlin!")
}

المخرجات:

TEXT 📖 للعرض فقط
Hello, Kotlin!

▶ مثال: المتغيرات والدوال

يوضح تعريف val (غير قابل للتغيير) و var (قابل للتغيير)، مع دالة بسيطة.

KOTLIN
val name = "Alice"
var age = 30
fun greet(n: String): String = "Hello, $n!"
println(greet(name))

المخرجات:

TEXT 📖 للعرض فقط
Hello, Alice!

▶ مثال: فئة البيانات

يوضح data class — توليد تلقائي لـ equals/hashCode/toString/copy.

KOTLIN
data class User(val name: String, val age: Int)
val alice = User("Alice", 30)
println(alice)

المخرجات:

TEXT 📖 للعرض فقط
User(name=Alice, age=30)

❓ أسئلة شائعة

س هل سيحل كوتلن محل جافا؟
ج لا. كوتلن مصمم للتعايش مع جافا، وليس لاستبدالها. كلاهما متوافق بنسبة 100% ويمكن خلطهما في نفس المشروع.
س هل يمكن لجافا استدعاء الرمز الثانوي المُترجَل من كوتلن؟
ج نعم. كوتلن يُنتج رمز JVM ثانوي قياسي — يمكن لكود جافا استدعاء فئات وطرق كوتلن مباشرة.
س هل أحتاج لتعلم جافا قبل كوتلن؟
ج ليس مطلوبًا، لكن خلفية جافا تُسرّع التعلم. العديد من ميزات كوتلن هي تحسينات على مشاكل جافا، لذا فهم جافا يساعدك على تقدير مزايا كوتلن.
س هل كوتلن أبطأ من جافا في وقت التشغيل؟
ج فرق ضئيل. كوتلن يُترجَل إلى نفس رمز JVM الثانوي الذي يعمل على نفس JVM. في بعض الحالات (الدوال المضمنة)، يمكن أن يكون كوتلن أسرع.
س هل كوتلن لأندرويد فقط؟
ج لا. كوتلن يدعم خلفية JVM، Native (iOS/macOS)، JavaScript، وWasm. أندرويد هي مجرد واحدة من منصاته.
س كيف يقارن كوتلن بـ Scala؟
ج كوتلن يعطي الأولوية للعملية والتوافق مع جافا بمنحنى تعلم سهل. Scala يميل إلى النقاء الأكاديمي والوظيفي — أقوى لكن أكثر تعقيدًا. كوتلن أيضًا يُترجَم أسرع بكثير من Scala.

📖 ملخص


📝 تمارين

  1. أساسي (⭐) : ثبّت بيئة كوتلن وشغّل برنامج Hello World. تلميح: استخدم IntelliJ IDEA أو سطر أوامر kotlinc
  2. متوسط (⭐⭐) : أعد كتابة فئة POJO بيانات جافا كـ data class كوتلن، ثم قارن عدد الأسطر. تلميح: لاحظ getter/equals/hashCode المُولَّد تلقائيًا
  3. تحدي (⭐⭐⭐) : ابحث في آلية expect/actual لكوتلن متعدد المنصات. اكتب دالة تسجيل مشتركة تُخرج على كل من منصتي JVM وJS. تلميح: راجع مثال الكود متعدد المنصات في القسم 4

التالي ←

Web-Tutorial.com

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

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

100%