2017-10-22 22 views
6

मेरे पास एक इंटरफ़ेस है जिसमें टी और कुछ मेटाडेटा की सरणी (या सूची) शामिल है।कोटलिन जेनेरिक ऐरे <T> परिणाम "टी को एक संशोधित प्रकार पैरामीटर के रूप में उपयोग नहीं कर सकते हैं। इसके बजाए कक्षा का उपयोग करें" लेकिन सूची <T>

interface DataWithMetadata<T> { 
    val someMetadata: Int 
    fun getData(): Array<T> 
} 

अगर मैं इंटरफेस का सबसे सरल कार्यान्वयन लिखते हैं, मैं पर एक संकलन त्रुटि मिलती है emptyArray(): "एक reified प्रकार पैरामीटर के रूप में टी उपयोग नहीं कर सकते बजाय एक वर्ग का प्रयोग करें।।"

class ArrayWithMetadata<T>(override val someMetadata: Int): DataWithMetadata<T> { 
    private var myData: Array<T> = emptyArray() 

    override fun getData(): Array<T> { 
     return myData 
    } 

    fun addData(moreData: Array<T>) { 
     this.myData += moreData 
    } 
} 

हालांकि, अगर मैं दोनों इंटरफेस और एक सूची में कार्यान्वयन बदलने के लिए, मेरे पास कोई संकलन समय मुद्दे हैं:

interface DataWithMetadata<T> { 
    val someMetadata: Int 
    fun getData(): List<T> 
} 

class ListWithMetadata<T>(override val someMetadata: Int): DataWithMetadata<T> { 
    private var myData: List<T> = emptyList() 

    override fun getData(): List<T> { 
     return myData 
    } 

    fun addData(moreData: Array<T>) { 
     this.myData += moreData 
    } 
} 

मुझे लगता है कि मेरे इस मुद्दे को अंदर Kotlin जेनरिक में कुछ दिलचस्प सबक है । क्या कोई मुझे बता सकता है कि संकलक हुड के नीचे क्या कर रहा है और क्यों ऐरे विफल रहता है लेकिन सूची नहीं है? इस संदर्भ में ऐरे कार्यान्वयन संकलन करने के लिए कोई मूर्ख तरीका है?

बोनस प्रश्न: सूची में ऐरे के लिए पहुंचने का एकमात्र कारण यह है कि मैं अक्सर कोटलिन डेवलपर्स को Arrays के पक्ष में देखता हूं। क्या यह मामला है, और यदि हां, तो क्यों?

public inline fun <reified @PureReifiable T> emptyArray(): Array<T> 

reified प्रकार पैरामीटर मतलब है कि आप संकलन समय पर T के वर्ग की पहुंच है:

उत्तर

5

kotlin stdlib (JVM) में emptyArray() की घोषणा को देखते हुए, हम reified प्रकार पैरामीटर नोटिस और इसे T::class जैसे एक्सेस कर सकते हैं। आप Kotlin reference में reified टाइप पैरामीटर के बारे में अधिक पढ़ सकते हैं। चूंकि Array<T> जावा T[] पर संकलित करता है, इसलिए हमें संकलन-समय पर प्रकार जानने की आवश्यकता है, इसलिए reified पैरामीटर। अब

fun <T> emptyArray() : Array<T> = Array(0, { throw Exception() }) 

Cannot use T as a reified type parameter. Use a class instead.


, के emptyList() के कार्यान्वयन पर एक नज़र डालें:: आप reified कीवर्ड के बिना एक emptyArray() फ़ंक्शन लिखने का प्रयास करें, तो आप एक संकलक त्रुटि मिलेगी

public fun <T> emptyList(): List<T> = EmptyList 

इस कार्यान्वयन को T पैरामीटर की आवश्यकता नहीं है। यह केवल आंतरिक ऑब्जेक्ट EmptyList देता है, जो स्वयं List<Nothing> से प्राप्त होता है। कोटलिन प्रकार Nothingthrow कीवर्ड का रिटर्न-प्रकार है और एक मान है जो कभी भी (reference) मौजूद नहीं है। यदि कोई विधि Nothing लौटाती है, तो उस स्थान पर अपवाद फेंकने के बराबर है। इसलिए हम सुरक्षित रूप से Nothing का उपयोग सुरक्षित रूप से कर सकते हैं क्योंकि हर बार हम EmptyList.get() पर कॉल करेंगे, यह संकलक जानता है कि यह एक अपवाद लौटाएगा।


बोनस सवाल:

जावा और सी ++ से आ रहा है, मैं ArrayList या std::vector करने के लिए इस्तेमाल कर रहा हूँ उपयोग करने के लिए है कि सरणियों काफी आसान हो सकता है। मैं कुछ महीने के लिए कोटलिन का उपयोग करता हूं और मुझे आमतौर पर स्रोत कोड लिखते समय सरणी और सूचियों के बीच एक बड़ा अंतर दिखाई नहीं देता है।दोनों में उपयोगी उपयोगी विस्तार कार्य हैं जो समान तरीके से व्यवहार करते हैं। हालांकि, कोटलिन कंपाइलर सरणी और सूचियों को बहुत अलग करता है, क्योंकि कोटलिन टीम के लिए जावा इंटरऑपरेबिलिटी बहुत महत्वपूर्ण है। मैं आमतौर पर सूचियों का उपयोग करना पसंद करता हूं, और यही वह है जो मैं आपके मामले में भी अनुशंसा करता हूं।

2

समस्या है, कि एक Arrayमें पता होना चाहिए की सामान्य तत्व प्रकार समय है, जो यहाँ reified प्रकार पैरामीटर से निर्देशित होता है, के रूप में घोषणा में देखा संकलन:

public inline fun <reified @PureReifiable T> emptyArray(): Array<T> 

यह केवल है Array<String> या Array<Int> जैसे कंक्रीट सरणी बनाने के लिए संभव है लेकिन Array<T> टाइप नहीं करें।

इस answer में, आप कई कामकाज पा सकते हैं। आशा है कि आपको एक उपयुक्त तरीका मिल जाएगा।

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

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