2016-04-12 2 views
19

को मैं एक समारोह है कि एक List में हर आइटम है कि पहले या अंतिम आइटम नहीं है देता है लिखना चाहते हैं (बिंदु के माध्यम से)। फ़ंक्शन को इनपुट के रूप में एक सामान्य List<*> मिलता है। एक परिणाम केवल किया जाना चाहिये अगर सूची के तत्वों प्रकार Waypoint के होते हैं:Kotlin: कैसे सूची के साथ काम करने डाले: अनियंत्रित कास्ट: kotlin.collections.List <Kotlin.Any?> kotlin.colletions.List <Waypoint>

अनियंत्रित कास्ट: kotlin.collections

fun getViaPoints(list: List<*>): List<Waypoint>? { 

    list.forEach { if(it !is Waypoint) return null } 

    val waypointList = list as? List<Waypoint> ?: return null 

    return waypointList.filter{ waypointList.indexOf(it) != 0 && waypointList.indexOf(it) != waypointList.lastIndex} 
} 

जब List<*> को List<Waypoint> कास्टिंग, मैं चेतावनी मिलती है। सूची kotlin.colletions.List को

मैं इसे अन्यथा लागू करने के लिए एक तरह से समझ नहीं कर सकते हैं। इस चेतावनी के बिना इस समारोह को लागू करने का सही तरीका क्या है?

उत्तर

52

कोटलिन में, सामान्य मामले में रनटाइम पर जेनेरिक पैरामीटर की जांच करने का कोई तरीका नहीं है (जैसे List<T> की वस्तुओं की जांच करना, जो केवल एक विशेष मामला है), इसलिए विभिन्न जेनेरिक पैरामीटर के साथ एक सामान्य प्रकार का एक अन्य प्रकार कास्टिंग करना होगा एक चेतावनी उठाएं जब तक कि कास्ट variance bounds के भीतर न हो।

विभिन्न समाधान कर रहे हैं, हालांकि:

  • आप प्रकार की जाँच की है और आप काफी यकीन है कि कलाकारों के लिए सुरक्षित है कर रहे हैं। यह देखते हुए, आप suppress the warning@Suppress("UNCHECKED_CAST") के साथ कर सकते हैं।

    @Suppress("UNCHECKED_CAST") 
    val waypointList = list as? List<Waypoint> ?: return null 
    
  • उपयोग .filterIsInstance<T>() समारोह है, जो आइटम प्रकारों की जाँच करता है और पारित प्रकार के आइटम की सूची देता है:

    val waypointList: List<Waypoint> = list.filterIsInstance<Waypoint>() 
    
    if (waypointList.size != list.size) 
        return null 
    

    या एक बयान में एक ही:

    val waypointList = list.filterIsInstance<Waypoint>() 
        .apply { if (size != list.size) return null } 
    

    यह वांछित प्रकार की एक नई सूची तैयार करेगा (इस प्रकार अनचेक कास्ट से बचने के लिए), थोड़ा ओवरहेड पेश करना, लेकिन साथ ही यह आपको टीरेटिंग टी से बचाता है list के माध्यम से और प्रकारों की जांच (list.foreach { ... } लाइन में), इसलिए यह ध्यान देने योग्य नहीं होगा।साथ

    @Suppress("UNCHECKED_CAST") 
    inline fun <reified T : Any> List<*>.checkItemsAre() = 
         if (all { it is T }) 
          this as List<T> 
         else null 
    

    :

  • एक उपयोगिता समारोह उस प्रकार की जाँच करता है और एक ही सूची लौटाता है यदि प्रकार सही है, इस प्रकार डाली (अभी भी देखने के संकलक के दृष्टिकोण से अनियंत्रित) इसके अंदर encapsulating लिखें उपयोग:

    val waypointList = list.checkItemsAre<Waypoint>() ?: return null 
    
+2

बेहतरीन उत्तर! मैं list.filterIsInstance () समाधान चुनता हूं क्योंकि मुझे लगता है कि यह सबसे साफ समाधान है। – lukle

+3

ध्यान दें कि यदि आप ['filterIsInstance'] (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-is-instance.html) का उपयोग करते हैं और मूल सूची में एक अलग प्रकार के तत्व होते हैं आपका कोड चुपचाप उन्हें फ़िल्टर करेगा। कभी-कभी यह वही है जो आप चाहते हैं लेकिन कभी-कभी आपको 'IllegalStateException' या इसी तरह फेंक दिया जा सकता है। यदि बाद में मामला है तो आप जांचने के लिए अपनी विधि बना सकते हैं और फिर कास्ट कर सकते हैं: 'इनलाइन मजेदार इटेबल <*> .mapAsInstance() = map {it.apply {चेक (यह आर)} आर} ' – mfulton26

+0

नोट करें कि नोट करें '.apply' lambda के रिटर्न वैल्यू को वापस नहीं करता है, यह प्राप्त ऑब्जेक्ट देता है। यदि आप एक शून्य वापस करने का विकल्प चाहते हैं तो शायद आप '.takeIf' का उपयोग करना चाहते हैं। – bj0

2

जेनेरिक कक्षाओं के मामले में चेक की जांच नहीं की जा सकती है क्योंकि प्रकार की जानकारी रनटाइम में मिटा दी जाती है। लेकिन आप जांचते हैं कि सूची में सभी ऑब्जेक्ट्स Waypoint एस हैं ताकि आप @Suppress("UNCHECKED_CAST") के साथ चेतावनी को दबा सकें।

ऐसी चेतावनी से बचने के लिए आप Waypoint के लिए परिवर्तनीय वस्तुओं की एक List पारित करने के लिए की है। जब आप * का उपयोग कर रहे हैं लेकिन टाइप की गई सूची के रूप में इस सूची तक पहुंचने का प्रयास कर रहे हैं तो आपको हमेशा एक कलाकार की आवश्यकता होगी और यह कलाकार अनचेक किया जाएगा।

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