2016-01-30 5 views
8

में आत्म-संदर्भ प्रदान करता है, मैं अपने हैक को question के उत्तर से सामान्य करने की कोशिश कर रहा हूं।एक कोटलिन उपयोग फ़ंक्शन लिखना जो प्रारंभकर्ता

यह उस मूल्य को संदर्भित करने का एक तरीका प्रदान करना चाहिए जो अभी तक इसके प्रारंभिक (अंदर, सीधे नहीं, बल्कि लैम्ब्डा और ऑब्जेक्ट एक्सप्रेशन में) के अंदर बनाया गया है।

क्या मैं इस समय है:

class SelfReference<T>(val initializer: SelfReference<T>.() -> T) { 
    val self: T by lazy { 
     inner ?: throw IllegalStateException("Do not use `self` until initialized.") 
    } 

    private val inner = initializer() 
} 

fun <T> selfReference(initializer: SelfReference<T>.() -> T): T { 
    return SelfReference(initializer).self 
} 

यह काम करता है, इस उदाहरण देखें:

class Holder(var x: Int = 0, 
      val action:() -> Unit) 

val h: Holder = selfReference { Holder(0) { self.x++ } } 
h.action() 
h.action() 
println(h.x) //2 

लेकिन इस बिंदु रास्ते पर है, जिसमें initializer संदर्भ का निर्माण मूल्य self संपत्ति है।

और मेरे सवाल यह है: वहाँ SelfReference के पुनर्लेखन के लिए इतना है कि initializer बजाय self संपत्ति का उपयोग करने का एक तर्क (या एक रिसीवर) पारित हो जाता है एक तरीका है? इस प्रश्न को संशोधित किया जा सकता है: क्या किसी फ़ंक्शन में आलसी मूल्यांकन प्राप्तकर्ता/तर्क पारित करने या इस अर्थशास्त्र को किसी तरह से प्राप्त करने का कोई तरीका है?

कोड को बेहतर बनाने के अन्य तरीके क्या हैं?


युपीडी: एक संभव तरीका इस प्रकार यह it() initializer अंदर के रूप में इस्तेमाल किया जाएगा, एक समारोह है कि self रिटर्न पारित करने के लिए है। अभी भी अन्य लोगों की तलाश में है।

+1

आप [प्रतिनिधि गुण] (https://kotlinlang.org/docs/reference/delegated-properties.html#delegated-properties) के संयोजन का उपयोग करने में सक्षम हो सकते हैं, [देर से प्रारंभिक गुण] (https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties), और/या [इनलाइन फ़ंक्शंस] (https://kotlinlang.org/docs/reference/inline-functions.html#inline- फ़ंक्शन) इसे सामान्यीकृत करने के लिए।मेरा प्रयास (मुझे लगता है) काम करना चाहिए, लेकिन एक कोटलिन संकलन बग अभी ऐसा करने से रोक रहा है (https://youtrack.jetbrains.com/issue/KT-10878 देखें)। – mfulton26

उत्तर

0

आत्मनिर्भरता को फिर से लिखने का कोई तरीका है ताकि प्रारंभकर्ता को स्वयं संपत्ति का उपयोग करने के बजाय एक तर्क (या एक रिसीवर) पारित किया जा सके? इस प्रश्न को संशोधित किया जा सकता है: क्या किसी फ़ंक्शन में आलसी मूल्यांकन प्राप्तकर्ता/तर्क पारित करने या इस अर्थशास्त्र को किसी तरह से प्राप्त करने का कोई तरीका है?

मुझे यकीन है कि मैं पूरी तरह से आपके उपयोग के मामले को समझ में नहीं कर रहा हूँ, लेकिन यह आप के लिए क्या देख रहे हो सकता है:

fun initHolder(x: Int = 0, holderAction: Holder.() -> Unit) : Holder { 
    var h: Holder? = null 
    h = Holder(x) { h!!.holderAction() } 
    return h 
} 

val h: Holder = initHolder(0) { x++ } 
h.action() 
h.action() 
println(h.x) // 2 

यह काम करता है क्योंकि holderAction एक रिसीवर (Holder.() -> Unit) के साथ एक लैम्ब्डा है दे रही है रिसीवर के सदस्यों के लिए लैम्ब्डा पहुंच।

यह एक सामान्य समाधान है क्योंकि आप संबंधित Holder कन्स्ट्रक्टर के हस्ताक्षर को बदलने में सक्षम नहीं हो सकते हैं। यह ध्यान देने योग्य हो सकता है कि इस समाधान को वर्ग को खोलने की आवश्यकता नहीं है, अन्यथा एक माध्यमिक कन्स्ट्रक्टर का उपयोग करके उप-वर्ग के साथ एक समान दृष्टिकोण किया जा सकता है।

मैं SelfReference कक्षा बनाने के लिए इस समाधान को प्राथमिकता देता हूं जब परिवर्तन की आवश्यकता वाले कुछ वर्गों की संख्या होती है।

उपयोगी त्रुटि फेंकने के लिए आप !! का उपयोग करने के बजाय null की जांच कर सकते हैं। यदि धारक action को इसके कन्स्ट्रक्टर या इनिट ब्लॉक में कॉल करता है, तो आपको एक शून्य सूचक अपवाद मिलेगा।

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