Kotlin में reified क्या है और इसे "जादू" क्यों कहा जाता है?
अगर आपने कभी Java में प्रोग्रामिंग की है, तो आपने Type Erasure का सामना ज़रूर किया होगा — रनटाइम पर टाइप की जानकारी मिट जाना। Java (और डिफ़ॉल्ट रूप से Kotlin) में, जेनेरिक्स के अंदर टाइप की जानकारी सिर्फ कंपाइल टाइम पर उपलब्ध होती है, रनटाइम पर यह गायब हो जाती है। इसका मतलब है कि आप सामान्य फंक्शन के अंदर if (value is T) या T::class नहीं लिख सकते, क्योंकि रनटाइम पर T सिर्फ Object होता है।
लेकिन Kotlin ने एक कदम आगे बढ़कर यह संभव बना दिया है। reified कीवर्ड (अंग्रेज़ी के "reified" यानी "मूर्त रूप दिया गया") आपको inline फंक्शन के अंदर टाइप को "जीवित" रखने की अनुमति देता है। reified की मदद से आप वह कर सकते हैं जो Java में असंभव लगता था: टाइप चेक करना, KClass प्राप्त करना, इंस्टेंस बनाना और यहां तक कि रिफ्लेक्शन के साथ काम करना — और यह सब रनटाइम पर।
इस लेख में, हम वास्तविक उदाहरणों के साथ समझेंगे कि reified कैसे काम करता है, जिन्हें आप तुरंत अपने प्रोजेक्ट में इस्तेमाल कर सकते हैं। चलिए शुरू करते हैं!
समस्या: Type Erasure का असली रूप
कल्पना करें: आप एक फंक्शन लिख रहे हैं जो जाँच करे कि कोई ऑब्जेक्ट स्ट्रिंग है या नहीं। एक सामान्य प्रयास:
fun <T> isString(value: Any): Boolean {
return value is T // कंपाइल करने पर एरर!
}
कंपाइलर एक एरर देगा: "Cannot check for instance of erased type: T"। ऐसा क्यों? क्योंकि रनटाइम पर JVM को नहीं पता कि T क्या है। उसके लिए T सिर्फ Object है।
यही बात क्लास प्राप्त करने पर भी लागू होती है: सामान्य फंक्शन के अंदर T::class भी काम नहीं करेगा। यही है Type Erasure — Java डेवलपर्स का सबसे बड़ा सिरदर्द।
समाधान: reified + inline
Kotlin एक सुंदर समाधान प्रदान करता है। रनटाइम पर टाइप को "याद" रखने के लिए, फंक्शन को inline बनाएं और टाइप पैरामीटर को reified कीवर्ड से चिह्नित करें:
inline fun <reified T> isString(value: Any): Boolean {
return value is T // अब यह काम करता है!
}
अब आप इसे कॉल कर सकते हैं:
println(isString<String>("Hello")) // true
println(isString<Int>("Hello")) // false
यह कैसे काम करता है? जब आप फंक्शन को inline चिह्नित करते हैं, तो कंपाइलर उसके कोड को सीधे कॉल वाली जगह पर डाल देता है। और reified कंपाइलर को जनरेटेड कोड में T की जगह विशिष्ट टाइप (जैसे String) डालने के लिए मजबूर करता है। नतीजतन, बाइट-कोड में स्पष्ट जाँच value is String दिखाई देती है।
reified के व्यावहारिक उदाहरण
आइए कुछ वास्तविक परिदृश्य देखें जहाँ reified वास्तव में जीवन को आसान बनाता है।
1. रनटाइम पर क्लास प्राप्त करना
सबसे आम कार्यों में से एक है टाइप-पैरामीटर से KClass या Class प्राप्त करना। reified के बिना यह असंभव है:
inline fun <reified T> getKClass(): KClass<T> = T::class
// उपयोग:
val kClass = getKClass<String>()
println(kClass.simpleName) // String
यह विशेष रूप से उन लाइब्रेरीज़ के साथ काम करते समय उपयोगी है जिन्हें रिफ्लेक्शन की आवश्यकता होती है (जैसे, सीरियलाइज़ेशन, ORM, DI-कंटेनर)।
2. टाइप के अनुसार इंस्टेंस बनाना
कंस्ट्रक्टर पास किए बिना वांछित टाइप का ऑब्जेक्ट बनाना चाहते हैं? आसान है:
inline fun <reified T : Any> createInstance(): T {
return T::class.createInstance()
}
// उदाहरण:
val instance = createInstance<StringBuilder>()
instance.append("Hello, reified!")
लेकिन सावधान रहें: createInstance() तभी काम करता है जब क्लास में बिना पैरामीटर वाला कंस्ट्रक्टर हो। अन्यथा, आपको एक अपवाद मिलेगा।
3. कलेक्शन में टाइप के अनुसार फ़िल्टर करना
मान लीजिए, आपके पास विभिन्न टाइप के ऑब्जेक्ट्स की एक सूची है, और आप सिर्फ स्ट्रिंग्स को फ़िल्टर करना चाहते हैं। Kotlin की स्टैंडर्ड लाइब्रेरी में filterIsInstance<T>() है, लेकिन आप आसानी से अपना वर्ज़न लिख सकते हैं:
ब्लॉग
पुस्तक अनुशंसाएँ
यह भी पढ़ें