परिचय
Kotlin दो तंत्र प्रदान करता है जब प्रॉपर्टी को तुरंत इनिशियलाइज़ नहीं किया जा सकता: lateinit (var के लिए) और by lazy (val के लिए)। दोनों डिफर्ड इनिशियलाइज़ेशन सक्षम करते हैं लेकिन अलग-अलग उपयोग के मामले हैं।
lateinit (लेट इनिशियलाइज़ेशन)
नियम:
- केवल var के साथ (परिवर्तनीय)
- केवल non-null टाइप्स के साथ
- प्रिमिटिव टाइप्स के साथ काम नहीं करता (Int, Boolean, आदि)
- कस्टम गेटर/सेटर नहीं हो सकते
- चेक करने के लिए `::property.isInitialized` का उपयोग करें
उदाहरण:
class Tutorial {
lateinit var name: String
fun checkLateInit() {
// इनिशियलाइज़ेशन चेक करें
if (::name.isInitialized) {
println("नाम पहले से इनिशियलाइज़्ड: $name")
} else {
println("नाम अभी तक इनिशियलाइज़्ड नहीं")
name = "www.tutorialspoint.com"
println("अब इनिशियलाइज़्ड: $name")
}
}
fun reset() {
// lateinit को रीसेट नहीं किया जा सकता, केवल पुनः असाइन
name = "नया मान"
}
}
fun main() {
val obj = Tutorial()
obj.checkLateInit() // पहले इनिशियलाइज़ करता है
obj.checkLateInit() // पहले से इनिशियलाइज़्ड दिखाता है
}
आउटपुट
नाम अभी तक इनिशियलाइज़्ड नहीं अब इनिशियलाइज़्ड: www.tutorialspoint.com नाम पहले से इनिशियलाइज़्ड: www.tutorialspoint.com
by lazy (लेज़ी इनिशियलाइज़ेशन)
नियम:
- केवल val के साथ (अपरिवर्तनीय रेफरेंस)
- थ्रेड-सेफ डिफ़ॉल्ट रूप से (`LazyThreadSafetyMode.SYNCHRONIZED`)
- केवल पहली एक्सेस पर इनिशियलाइज़ होता है
- बाद के एक्सेस के लिए मान कैश करता है
- पुनः असाइन नहीं किया जा सकता
उदाहरण:
class Demo {
val myName: String by lazy {
println("लेज़ी इनिशियलाइज़ेशन हो रहा है...")
"www.tutorialspoint.com"
}
// अलग थ्रेड-सेफ्टी मोड
val threadLocal: String by lazy(LazyThreadSafetyMode.PUBLICATION) {
"प्रकाशन मोड"
}
val noSync: String by lazy(LazyThreadSafetyMode.NONE) {
"कोई सिंक नहीं"
}
}
fun main() {
val obj = Demo()
println("पहली कॉल: ${obj.myName}")
println("दूसरी कॉल: ${obj.myName}") // कैश्ड मान
println("तीसरी कॉल: ${obj.myName}") // कैश्ड मान
}
आउटपुट
लेज़ी इनिशियलाइज़ेशन हो रहा है... पहली कॉल: www.tutorialspoint.com दूसरी कॉल: www.tutorialspoint.com तीसरी कॉल: www.tutorialspoint.com
तुलना तालिका
| पहलू | lateinit var | by lazy val |
|---|---|---|
| परिवर्तनीयता | परिवर्तनीय (var) | अपरिवर्तनीय रेफरेंस (val) |
| इनिशियलाइज़ेशन ट्रिगर | मैन्युअल असाइनमेंट | पहली एक्सेस पर स्वचालित |
| पुनः असाइनमेंट | अनुमत | अनुमत नहीं |
| थ्रेड-सेफ्टी | नहीं (मैन्युअल सिंक आवश्यक) | हाँ (डिफ़ॉल्ट SYNCHRONIZED) |
| नल अनुमत | नहीं | नहीं (लेकिन nullable val के साथ उपयोग कर सकते हैं) |
| प्रिमिटिव टाइप्स | नहीं | नहीं (लेकिन wrapper types के साथ) |
| इनिशियलाइज़ेशन चेक | `::prop.isInitialized` | N/A (हमेशा एक्सेस पर इनिशियलाइज़्ड) |
| उपयोग का मामला | डिपेंडेंसी इंजेक्शन, व्यू बाइंडिंग | महंगी गणना, सिंगलटन |
व्यावहारिक उदाहरण
lateinit उपयोग मामला: व्यू बाइंडिंग / डिपेंडेंसी इंजेक्शन
class MainActivity : AppCompatActivity() {
// onCreate में इनिशियलाइज़ होगा
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) // यहां इनिशियलाइज़
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
setContentView(binding.root)
}
}
by lazy उपयोग मामला: महंगी गणना / सिंगलटन
class Repository {
// डेटाबेस कनेक्शन - केवल जब पहली बार जरूरत हो
val database: AppDatabase by lazy {
Room.databaseBuilder(context, AppDatabase::class.java, "db").build()
}
// रेट्रोफिट इंस्टेंस
val apiService: ApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.build()
.create(ApiService::class.java)
}
}
सारांश
- lateinit var - जब आप बाद में मैन्युअल रूप से इनिशियलाइज़ करेंगे (DI, व्यू बाइंडिंग, टेस्ट सेटअप)
- by lazy val - जब मान महंगा हो और पहली एक्सेस पर ऑन-डिमांड गणना करना चाहते हैं
- दोनों non-null टाइप्स के लिए हैं
- प्रिमिटिव टाइप्स के लिए nullable wrapper या `LateInit`/`Lazy` डेलीगेट्स का उपयोग करें