2017-03-11 6 views
6

मैं वर्तमान में एक पुस्तकालय के लिए एक डीएसएल लिख रहा हूँ और मैं इस तरह reified प्रकार पैरामीटर्स का उपयोग प्रकार मेटाडाटा आपूर्ति करने के लिए करना चाहते हैं:मैं कोटलिन में उदाहरण फ़ील्ड में संशोधित प्रकार डेटा कैसे संग्रहीत कर सकता हूं?

val config = Config.create() 
      .consumerFor<MyType>{ 
       // consume 
      } 

मेरे समस्या यह है कि मैं केवल inline कार्यों में reified कीवर्ड का उपयोग कर सकते है और

Public-API inline function cannot access non-public-API 'private final val consumers...

: क्योंकि मैं कोई त्रुटि मिलती है

inline fun <reified T> consumerFor(consumer: (T) -> Unit) { 
     consumers.put(T::class.java, consumer) 
     return this 
    } 

: एक inline समारोह में मैं इस तरह दृष्टांत फ़ील्ड उपयोग नहीं कर सकते

ऐसा लगता है कि मैं संशोधित प्रकार पैरामीटर का उपयोग नहीं कर सकता जहां वे सबसे उपयोगी होंगे। क्या इसके आसपास कोई कार्य है?

उत्तर

6

लोक inline कार्यों private घोषणाओं सीधे उपयोग नहीं कर सकते, क्योंकि जब कक्षा के बाहर कॉल स्थलों पर inlined, उपयोगों के गलत पहुंच का स्तर होगा (JVM पर, एक वर्ग का एक private सदस्य बाहर से पहुँचा नहीं जा सकता)।

क्या आप कर सकते हैं कोटलिन में the internal visibility का उपयोग करें: जेवीएम पर, इस दृश्यता संशोधक वाले सदस्यों को सार्वजनिक सदस्यों में उनके नामों के साथ संकलित किया जाएगा (इसलिए अभी भी दिखाई दे रहा है लेकिन जावा से आसान नहीं है), और कोटलिन कंपाइलर कम से कम कोटलिन कोड से उपयोग को नियंत्रित करेगा।

एक public inline fun के भीतर से एक internal सदस्य तक पहुँचने के लिए, इस सवाल को देखने के लिए कुछ तरीके हैं:, (link)

अपने विशेष मामले में मैं @PublishedApi साथ यह कर पसंद करते हैं:

private val consumers = mutableMapOf<Class<*>, Any>() 

@PublishedApi 
internal fun <T> putConsumer(clazz: Class<out T>, consumer: (T) -> Unit) { 
    consumers.put(clazz, consumer) 
} 

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit): C { 
    putConsumer(T::class.java, consumer) 
    return this 
} 

या, अगर आपको consumers@PublishedApi के साथ उजागर करने में कोई फर्क नहीं पड़ता है, तो आप इसे निम्न प्रकार से कर सकते हैं:

@PublishedApi 
internal val consumers = mutableMapOf<Class<*>, Any>() 

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit): C { 
    consumers.put(T::class.java, consumer) 
    return this 
} 
+0

यह ठीक होगा, धन्यवाद। यह अंतिम फ़ील्ड के साथ सिर्फ एक कॉन्फ़िगरेशन क्लास है इसलिए मुझे कोई फर्क नहीं पड़ता। –

1

यदि आपके पास जावा श्रेणी को प्रतिबिंबित करने के लिए सभी प्रकार के संशोधित प्रकार पैरामीटर की आवश्यकता है, तो आप अतिरिक्त Class<T> पैरामीटर के साथ एक गैर-इनलाइन ओवरलोड के साथ प्रबंधित कर सकते हैं।

inline fun <reified T> consumerFor(noinline consumer: (T) -> Unit) = 
    consumerFor(T::class.java, consumer) 

fun <T> consumerFor(key: Class<T>, consumer: (T) -> Unit) = apply { 
    consumers.put(key, consumer) 
} 

इस तरह आपने consumers संपत्ति को प्रभावी ढंग से प्रकाशित नहीं किया है। बोनस प्वाइंट यह है कि आप जावा से भी गैर-इनलाइन ओवरलोड को कॉल कर सकते हैं।

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

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