0Pricing
Kotlin Academy · درس

‏lateinit والتهيئة الكسولة

استخدم lateinit للخصائص التي تُسنَد لاحقًا، وby lazy للحساب المؤجل.

‏lateinit والتهيئة الكسولة درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

أداتان للتهيئة المتأخرة

أحيانًا لا يمكنك تهيئة خاصية وقت إنشاء الكائن. توفر Kotlin أداتَي lateinit (لـ var تُسنَد قيمتها لاحقًا) وby lazy (لـ val تُحسب عند أول وصول إليها).

أساسيات lateinit

تؤجل lateinit var التهيئة. يجب أن يكون المتغير var غير قابل للقيمة الفارغة وغير بدائي. ويؤدي الوصول إليه قبل إسناد قيمة إلى رمي UninitializedPropertyAccessException.

class Service {
    lateinit var name: String
    fun init(value: String) { name = value }
}
fun main() {
    val s = Service()
    s.init("MyService")
    println(s.name)
}

لماذا نستخدم lateinit؟

استخدم lateinit لحقن الاعتماديات، أو تجهيزات الاختبارات، أو دورات الحياة التي تديرها الأطر (مثل Android views وSpring beans)، حيث تحدث التهيئة خارج الباني.

class Repository {
    lateinit var db: String   // assigned later by DI framework
    fun query() = "querying $db"
}
fun main() {
    val r = Repository()
    r.db = "postgres://localhost"
    println(r.query())
}

التحقق باستخدام isInitialized

يمكنك التحقق مما إذا كانت خاصية lateinit قد أُسنِدت إليها قيمة باستخدام ::propName.isInitialized.

class Foo {
    lateinit var bar: String
    fun status() = if (::bar.isInitialized) "set to $bar" else "unset"
}
fun main() {
    val f = Foo()
    println(f.status()) // unset
    f.bar = "hi"
    println(f.status())
}

قيود lateinit

لا يمكنك استخدام lateinit مع الأنواع البدائية (مثل Int وBoolean وغيرها)، أو الأنواع القابلة للقيمة الفارغة، أو val. يفرض المترجم هذه القواعد.

// VALID:
lateinit var name: String
// INVALID:
// lateinit var count: Int       // primitives not allowed
// lateinit val constant: String // val not allowed
// lateinit var maybe: String?   // nullable not allowed
fun main() { name = "ok"; println(name) }

أساسيات by lazy

تؤجل by lazy تهيئة val حتى أول وصول إليها. وتُنفَّذ lambda مرة واحدة، ثم تُخزَّن النتيجة مؤقتًا.

val expensive: String by lazy {
    println("Computing...")
    "result"
}
fun main() {
    println(expensive) // Computing... then result
    println(expensive) // result (cached)
}

لماذا نستخدم by lazy؟

استخدم by lazy عندما تكون التهيئة مكلفة وقد لا تكون مطلوبة (مع تخزينها مؤقتًا لاستخدامها لاحقًا)، أو عندما تعتمد التهيئة على خصائص أخرى سبق إنشاؤها.

class Config {
    val parsed: Map<String, String> by lazy {
        println("parsing config...")
        mapOf("host" to "localhost", "port" to "8080")
    }
}
fun main() {
    val c = Config()
    println("config object created — not parsed yet")
    println(c.parsed["host"]) // now parses
    println(c.parsed["port"]) // cached
}

أوضاع أمان الخيوط في lazy

تستخدم by lazy افتراضيًا LazyThreadSafetyMode.SYNCHRONIZED. استخدم PUBLICATION عندما تكون التهيئة المتزامنة مقبولة، وNONE لتحسين الأداء في التنفيذ أحادي الخيط.

val safe: String by lazy { "thread-safe" }
val fast: String by lazy(LazyThreadSafetyMode.NONE) { "fast, single-thread" }
fun main() {
    println(safe)
    println(fast)
}

‏lateinit في مقابل lazy

lateinit: ‏var تُسنَد قيمتها خارجيًا. by lazy: ‏val تحسبها الخاصية نفسها عند أول وصول إليها.

class Demo {
    lateinit var injected: String         // assigned by caller
    val computed: String by lazy { "computed once" }
}
fun main() {
    val d = Demo()
    d.injected = "from outside"
    println(d.injected)
    println(d.computed)
}

قراءة خصائص أخرى باستخدام lazy

يمكن لخاصية lazy قراءة خصائص أخرى (تمت تهيئتها مسبقًا) ودمجها.

class User(val first: String, val last: String) {
    val fullName: String by lazy { "$first $last" }
}
fun main() {
    val u = User("Ada", "Lovelace")
    println(u.fullName)
}

نمط عملي

اجمع بين lateinit لحقن الاعتماديات وby lazy للحالة المشتقة داخل الفئة نفسها.

class App {
    lateinit var config: Map<String, String>
    val host: String by lazy { config["host"] ?: "localhost" }
}
fun main() {
    val app = App()
    app.config = mapOf("host" to "api.example.com")
    println(app.host) // api.example.com
}

تحقق سريع

أي كلمة محجوزة تؤجل تهيئة خاصية val حتى أول وصول إليها؟

مراجعة

استخدم lateinit var للخصائص القابلة للتغيير وغير القابلة للقيمة الفارغة التي تُسنَد قيمتها لاحقًا بواسطة الأطر أو حقن الاعتماديات. استخدم val by lazy للقيم للقراءة فقط التي ينبغي حسابها مرة واحدة عند أول وصول إليها. تحقّق من الحالة باستخدام ::prop.isInitialized.

الأسئلة الشائعة

هل درس «‏lateinit والتهيئة الكسولة» مجاني؟

نعم — نص درس «‏lateinit والتهيئة الكسولة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «‏lateinit والتهيئة الكسولة»؟

استخدم lateinit للخصائص التي تُسنَد لاحقًا، وby lazy للحساب المؤجل. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «‏lateinit والتهيئة الكسولة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. المنشئ الأساسي ومعاملات الخصائص
  2. كتل init وترتيب التهيئة
  3. أدوات Getter وSetter مخصصة مع field
  4. ‏lateinit والتهيئة الكسولة
← العودة إلى Kotlin Academy