2017-08-20 8 views
5

मैं प्रतिबिंब के साथ खेल रहा हूं और मैं इस समस्या से बाहर आया हूं। जब ::class वाक्य रचना के माध्यम से बाध्य वर्ग संदर्भ का उपयोग करते हुए, मैं एक covariant KClass प्रकार मिलता है:बाध्य वर्ग संदर्भ रखने का उद्देश्य एक कॉन्वेंट प्रकार कैसे लौटाता है?

fun <T> foo(entry: T) { 
    with(entry::class) { 
     this // is instance of KClass<out T> 
    } 
} 

मैं डॉक्स से सीख सकते हैं के रूप में, इस वस्तु का सही प्रकार वापस आ जाएगी, मामले में यह एक उप प्रकार का उदाहरण है T, इसलिए भिन्नता संशोधक। हालांकि इस गुण T वर्ग में घोषित पुन: प्राप्त करने और उनके मूल्य हो रही

fun <T> foo(entry: T) { 
    with(entry::class) { 
     for (prop in memberProperties) { 
      val v = prop.get(entry) //compile error: I can't consume T 
     } 
    } 
} 

मैंने पाया कि एक समाधान ऑब्जेक्ट संदर्भ पर javaClass.kotlin विस्तार समारोह उपयोग कर रहा है (जो कि मैं क्या करने की कोशिश कर रहा हूँ है) को रोकता है, प्राप्त करने के लिए बजाय अपरिवर्तनीय प्रकार:

fun <T> foo(entry: T) { 
    with(entry.javaClass.kotlin) { 
     this // is instance of KClass<T> 
    } 
} 

इस तरह, मैं क्रम में सही प्रकार और प्रकार का उपभोग करने के संभावना दोनों मिलता है।

class Derived: Base() 

fun foo(entry: Base) { 
    with(entry.javaClass.kotlin) { 
     println(this == Derived::class) 
    } 
} 

fun main(args: Array<String>) { 
    val derived = Derived() 
    foo(derived) // prints 'true' 
} 

अगर मैं यह सही है, ::class है:

दिलचस्प है, अगर मैं एक महाप्रकार बजाय का उपयोग एक सामान्य की, बाद विधि के साथ मैं अभी भी सही प्रकार के लिए उपयोग, विचरण के आवश्यकता के बिना प्राप्त जावा getClass को कॉल करने के बराबर, जो वाइल्डकार्ड के साथ एक प्रकार का प्रकार देता है, जबकि javaClass विशिष्ट प्रकार के कलाकार के साथ getClass है। फिर भी, मुझे नहीं लगता कि मुझे कभी भी एक कॉन्वेंट KClass क्यों चाहिए, जब यह मुझे केवल प्रकार का उत्पादन करने के लिए सीमित करता है, यह देखते हुए कि रनटाइम पर सटीक कक्षा तक पहुंचने के अन्य तरीके हैं और इसे स्वतंत्र रूप से उपयोग करें, और मुझे आश्चर्य है कि क्या अधिक तत्काल ::class को डिज़ाइन द्वारा एक आविष्कार प्रकार वापस करना चाहिए।

उत्तर

3

::class संदर्भों में कॉन्वर्सिस का कारण यह है कि अभिव्यक्ति का घोषित या अनुमानित प्रकार से अलग हो सकता है, अभिव्यक्ति का मूल्यांकन करने वाले ऑब्जेक्ट का वास्तविक रनटाइम प्रकार।

उदाहरण:

open class Base 
class Derived : Base() 

fun someBase(): Base = Derived() 

val kClass = someBase()::class 

अभिव्यक्ति someBase()Base के रूप में लिखा गया है, लेकिन क्रम में यह एक Derived वस्तु है कि यह करने के लिए मूल्यांकन किया जाता हो जाता है।

टाइपिंग someBase()::class इनवेरिएंट KClass<Base> के रूप में टाइप करना वास्तव में गलत है, वास्तव में, इस अभिव्यक्ति का मूल्यांकन करने का वास्तविक परिणाम KClass<Derived> है। someBase()::class, KClass<out Base> है जिसका अर्थ है कि रनटाइम पर someBase()Base की एक उप-प्रकार हो सकता है, और इसलिए इस एक वर्ग हो सकता है:

यह संभव विसंगति (कि टूट प्रकार- सुरक्षा के लिए नेतृत्व करेंगे), सभी के लिए बाध्य श्रेणी संदर्भ covariant हैं हल करने के लिए Base के उप प्रकार का टोकन।

यह वह जगह है, ज़ाहिर है, नहीं अनबाउंड श्रेणी संदर्भ के साथ मामला: जब आप Base::class लेते हैं, आप अपने उप-प्रकारों में से कुछ की नहीं निश्चित रूप से पता है कि यह Base के वर्ग टोकन है और, इसलिए यह अपरिवर्तनीय KClass<Base> है।

+0

मैं समझता हूं कि आप क्या कहते हैं। लेकिन मेरा मुद्दा यह है कि अगर मैं कुछबेस()। JavaClass का उपयोग करता हूं।कोटलिन, मेरे पास अभी भी रनटाइम पर सही उप प्रकार (व्युत्पन्न) है लेकिन संकलन समय पर कोई भिन्नता नहीं है, क्योंकि उन एक्सटेंशन फ़ंक्शंस जेनरिक का उपयोग करते हैं। ऐसा लगता है कि :: क्लास सिंटैक्स को जावा क्लास.कोटलिन जैसे काम में सुधार किया जा सकता है, जो कि निष्क्रिय रूप से कम तत्काल भी है। ऐसा लगता है कि वे एक ही काम करते हैं, एक कोटलिन वर्ग लौटते हैं, लेकिन बाद में बेहतर वर्कोज़ होता है जबकि अधिक वर्बोज़ – devrocca

+0

यह दूसरी तरफ है: '.javaClass' पहले पेश किया गया था, और इसमें भिन्नता की अनुपस्थिति थी एक गलत डिजाइन माना जाता है; '.javaClass' को भी हटा दिया गया है [(1.1 आरसी में)] (https://blog.jetbrains.com/kotlin/2017/02/kotlin-1-1-release-candidate-is-here/), लेकिन फिर, 1.1 अंतिम रिलीज में, बहिष्करण हटा दिया गया था। – hotkey

+0

दिलचस्प बात। फिर भी, अगर मुझे प्रतिबिंब के माध्यम से प्राप्त संपत्तियों को कॉल करना है, तो मुझे एक रिसीवर की आवश्यकता है और कॉन्वेंट प्रकार मुझे बाध्यता का उपयोग नहीं करने देगा। हाइपोटैथिक मामले में आप यह कैसे करेंगे कि '.javaClass' उपलब्ध नहीं था? – devrocca

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