2016-05-03 3 views
9

मेरे पास सामान्य रूप से टाइप की गई कक्षा Builder<T> है जो एक कन्स्ट्रक्टर तर्क Class<T> लेता है ताकि मैं इस प्रकार को चारों ओर रख सकूं। यह एक वर्ग है जिसे मैं जावा कोड में बहुत उपयोग करता हूं इसलिए मैं हस्ताक्षर को बदलना नहीं चाहता हूं। जब मैं इस तरह निर्माता का उपयोग करने का प्रयास करें:जेनेरिक के साथ सूची की कक्षा प्राप्त करना उदाहरण: सूची <Number> :: कक्षा

Builder<List<Number>>(List<Number>::class)

मैं एक त्रुटि मिलती है: इस को हल करने

किसी भी तरह से "केवल कक्षाएं एक वर्ग शाब्दिक के बाएं हाथ की ओर अनुमति दी जाती है"? मैं Builder के लिए कन्स्ट्रक्टर नहीं बदल सकता, बहुत से जावा वर्ग इस पर भरोसा करते हैं।

मैं पूरे प्रकार के मिटा मुद्दे को समझता हूं, मैं वास्तव में संकलक को खुश करना चाहता हूं।

उत्तर

12

generic type erasureList कक्षा के कारण सभी सामान्य जेनेरिक इंस्टॉलेशन के लिए एक ही कार्यान्वयन है। आप केवल List<*> प्रकार से संबंधित कक्षा प्राप्त कर सकते हैं, और इस प्रकार केवल Builder<List<*>> बना सकते हैं।

वह निर्माता उदाहरण की सूची बनाने के लिए उपयुक्त है। और फिर क्या है जिसे आप अनियंत्रित डाले की मदद से खुद के द्वारा तय कर सकते हैं विलोपन टाइप करने के लिए कारण:

inline fun <reified T : Any> Builder() = Builder(T::class.java) 

और इसका इस्तेमाल करते हैं:

Builder(List::class.java) as Builder<List<Number>> 
Builder(List::class.java as Class<List<Number>>) 

एक और दृष्टिकोण इनलाइन reified सहायक समारोह बनाने के लिए है निम्नलिखित तरीके:

Builder<List<Number>>() 
+0

संशोधित तरीका – saarrrr

+1

है यह वास्तविक प्रकार पैरामीटर को बनाए रखेगा: 'T :: class.java' 'सूची <*>' का प्रतिनिधित्व करेगा, 'सूची ' नहीं, लेकिन एक समाधान है जो इसे संशोधित जेनरिक के लिए करेगा - - सुपर क्लास टोकन। – hotkey

+0

@hotkey मुझे लगता है कि 'बिल्डर' वर्ग को वास्तविक प्रकार के मानकों को बनाए रखने की आवश्यकता नहीं है, क्योंकि यह एक कन्स्ट्रक्टर तर्क 'कक्षा ' लेता है और प्रश्न में बताए गए अनुसार टाइप टाइप नहीं करता है। – Ilya

5

समाधान super class tokens साथ जोड़ी में reified generics उपयोग करने के लिए है।

कृपया समझाया गया विधि के लिए this question देखें। Kotlin में कंस्ट्रक्टर्स reified जेनरिक का समर्थन नहीं करते हैं, लेकिन आप TypeReference वहाँ वर्णित एक builder कारखाने समारोह जो रनटाइम पर वास्तविक सामान्य मापदंडों रख सकेंगे लिखने के लिए उपयोग कर सकते हैं:

inline <reified T: Any> fun builder(): Builder<T> { 
    val type = object : TypeReference<T>() {}.type 
    return Builder(type) 
} 

फिर Builder अंदर आप देख सकते हैं कि typeParameterizedType है, और यदि यह है, type.actualTypeArguments में वास्तविक सामान्य पैरामीटर होंगे।

उदाहरण के लिए, builder<List<Number>>() रनटाइम पर Number के बारे में जानकारी को बनाए रखेगा।

इस दृष्टिकोण की सीमा यह है कि आप गैर-संशोधित जेनेरिक को एक संशोधित प्रकार पैरामीटर के रूप में उपयोग नहीं कर सकते हैं क्योंकि प्रकार संकलन-समय पर जाना जाना चाहिए।

संबंधित मुद्दे