टीएल; डीआर: किसके लिए reifiedअच्छा है
fun <T> myGenericFun(c: Class<T>)
जैसे सामान्य कार्य के शरीर में myGenericFun, आप प्रकार तक नहीं पहुँच सकते Tक्योंकि यह केवल संकलन समय पर उपलब्ध है, लेकिन रनटाइम पर मिटा दिया गया है। इसलिए, यदि आप फ़ंक्शन बॉडी में एक सामान्य वर्ग के रूप में जेनेरिक प्रकार का उपयोग करना चाहते हैं, तो आपको कक्षा में दिखाए गए पैरामीटर के रूप में स्पष्ट रूप से पास करने की आवश्यकता है myGenericFun।
यदि आप किसी inlineफ़ंक्शन को किसी reified के साथ बनाते हैं T, तो Tरनटाइम पर भी एक्सेस किया जा सकता है और इस प्रकार आपको Class<T>इसके अतिरिक्त पास करने की आवश्यकता नहीं है । आप इसके साथ काम कर सकते हैं Tजैसे कि यह एक सामान्य वर्ग था, उदाहरण के लिए, आप जाँच सकते हैं कि क्या एक चर का एक उदाहरण है T , जिसे आप आसानी से देख सकते हैं myVar is T:।
प्रकार के inlineसाथ इस तरह के एक समारोह इस प्रकार है:reifiedT
inline fun <reified T> myGenericFun()
कैसे reifiedकाम करता है
आप केवल reifiedएक inlineफ़ंक्शन के साथ संयोजन में उपयोग कर सकते हैं । ऐसा फ़ंक्शन कंपाइलर को फ़ंक्शन के बाइटकोड को हर उस स्थान पर कॉपी करता है जहां फ़ंक्शन का उपयोग किया जा रहा है (फ़ंक्शन "इनबिल्ड" हो रहा है)। जब आप एक इनलाइन फ़ंक्शन को रिफ़ाइंड प्रकार के साथ कॉल करते हैं, तो कंपाइलर वास्तविक प्रकार को एक तर्क के रूप में जानता है और उत्पन्न बाइटकोड को सीधे संबंधित वर्ग का उपयोग करने के लिए संशोधित करता है। इसलिए जैसे कॉल myVar is Tबन myVar is String(यदि प्रकार तर्क थे Stringबाईटकोड में और रनटाइम पर)।
उदाहरण
आइए एक उदाहरण देखें जो दिखाता है कि कितना उपयोगी reifiedहो सकता है। हम Stringकॉल के लिए एक एक्सटेंशन फ़ंक्शन बनाना चाहते हैं जो toKotlinObjectफ़ंक्शन के जेनेरिक प्रकार द्वारा निर्दिष्ट प्रकार के साथ एक JSON स्ट्रिंग को सादे कोटलिन ऑब्जेक्ट में बदलने की कोशिश करता है T। हम इसके लिए उपयोग कर सकते हैं com.fasterxml.jackson.module.kotlinऔर पहला तरीका निम्नलिखित है:
क) पहले प्रकार के बिना पुनरीक्षित प्रकार
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.java)
}
readValueविधि एक प्रकार है कि यह पार्स करने के लिए चाहिए था लेता JsonObjectहै। यदि हम Classप्रकार के पैरामीटर को प्राप्त करने की कोशिश करते हैं T, तो कंपाइलर शिकायत करता है: "T 'को रिवाइज्ड टाइप पैरामीटर के रूप में उपयोग नहीं किया जा सकता है। इसके बजाय एक वर्ग का उपयोग करें।"
बी) स्पष्ट Classपैरामीटर के साथ समाधान
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
समाधान के लिए, Classकी Tएक विधि पैरामीटर, जो तब के लिए एक तर्क के रूप में इस्तेमाल किया जा सकता है readValue। यह काम करता है और जेनेरिक जावा कोड में एक सामान्य पैटर्न है। इसे इस प्रकार कहा जा सकता है:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
ग) कोटलिन रास्ता: reified
प्रकार पैरामीटर के inlineसाथ फ़ंक्शन का उपयोग करना फ़ंक्शन को अलग तरीके से लागू करना संभव बनाता है:reifiedT
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
लेने के लिए कोई ज़रूरत नहीं है Classकी Tइसके अतिरिक्त, Tइस्तेमाल किया जा सकता है कि यह एक साधारण वर्ग था। क्लाइंट के लिए कोड इस तरह दिखता है:
json.toKotlinObject<MyJsonType>()
महत्वपूर्ण नोट: जावा के साथ काम करना
reifiedप्रकार के साथ एक इनलाइन फ़ंक्शन जावा कोड से कॉल करने योग्य नहीं है ।