उच्च-क्रम के कार्य बहुत सहायक होते हैं और वे वास्तव reusability
में कोड में सुधार कर सकते हैं । हालांकि, उनका उपयोग करने के बारे में सबसे बड़ी चिंताओं में से एक दक्षता है। लैम्ब्डा अभिव्यक्तियों को कक्षाओं (अक्सर अनाम कक्षाओं) में संकलित किया जाता है, और जावा में ऑब्जेक्ट निर्माण एक भारी ऑपरेशन है। हम अभी भी उच्च-क्रम के कार्यों को प्रभावी तरीके से उपयोग कर सकते हैं, जबकि सभी लाभों को रखते हुए, फ़ंक्शन को इनलाइन बनाकर।
यहाँ तस्वीर में इनलाइन फ़ंक्शन आता है
जब एक फ़ंक्शन के रूप में चिह्नित किया जाता है inline
, तो कोड संकलन के दौरान कंपाइलर सभी फ़ंक्शन कॉल को फ़ंक्शन के वास्तविक निकाय से बदल देगा। साथ ही, तर्क के रूप में दिए गए लंबोदर भावों को उनके वास्तविक शरीर के साथ बदल दिया जाता है। उन्हें कार्यों के रूप में नहीं, बल्कि वास्तविक कोड के रूप में माना जाएगा।
संक्षेप में: - इनलाइन -> बुलाए जाने के बजाय, संकलन के समय उन्हें फ़ंक्शन के बॉडी कोड द्वारा बदल दिया जाता है ...
कोटलिन में, एक फ़ंक्शन को दूसरे फ़ंक्शन के पैरामीटर के रूप में उपयोग करना (जिसे उच्च-क्रम फ़ंक्शन कहा जाता है) जावा की तुलना में अधिक प्राकृतिक लगता है।
लैम्ब्डा का उपयोग करने के कुछ नुकसान हैं, हालांकि। चूंकि वे अनाम कक्षाएं हैं (और इसलिए, ऑब्जेक्ट), उन्हें मेमोरी की आवश्यकता होती है (और यहां तक कि आपके ऐप की समग्र विधि गणना में भी जोड़ सकते हैं)। इससे बचने के लिए, हम अपने तरीकों को इनलाइन कर सकते हैं।
fun notInlined(getString: () -> String?) = println(getString())
inline fun inlined(getString: () -> String?) = println(getString())
उपरोक्त उदाहरण से : - ये दोनों कार्य ठीक एक ही कार्य करते हैं - गेटस्ट्रिंग फ़ंक्शन के परिणाम को प्रिंट करना। एक अंतर्भूत है और एक नहीं है।
यदि आप विघटित जावा कोड की जाँच करते हैं, तो आप देखेंगे कि विधियाँ पूरी तरह से समान हैं। ऐसा इसलिए है क्योंकि इनलाइन कीवर्ड कॉल-साइट में कोड को कॉपी करने के लिए कंपाइलर को एक निर्देश है।
हालाँकि, अगर हम किसी फ़ंक्शन को नीचे दिए गए किसी अन्य फ़ंक्शन में पास कर रहे हैं:
//Compile time error… Illegal usage of inline function type ftOne...
inline fun Int.doSomething(y: Int, ftOne: Int.(Int) -> Int, ftTwo: (Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/
}
इसे हल करने के लिए, हम अपने फ़ंक्शन को नीचे के रूप में फिर से लिख सकते हैं:
inline fun Int.doSomething(y: Int, noinline ftOne: Int.(Int) -> Int, ftTwo: (Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/}
मान लें कि हमारे पास नीचे की तरह एक उच्च क्रम फ़ंक्शन है:
inline fun Int.doSomething(y: Int, noinline ftOne: Int.(Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/}
यहाँ, संकलक हमें इनलाइन कीवर्ड का उपयोग नहीं करने के लिए कहेगा जब केवल एक लैम्ब्डा पैरामीटर है और हम इसे किसी अन्य फ़ंक्शन में भेज रहे हैं। इसलिए, हम नीचे दिए गए फ़ंक्शन को फिर से लिख सकते हैं:
fun Int.doSomething(y: Int, ftOne: Int.(Int) -> Int) {
//passing a function type to another function
val funOne = someFunction(ftOne)
/*...*/
}
नोट : -हम को कीवर्ड नॉयलाइन को भी हटाना पड़ा क्योंकि इसका उपयोग केवल इनलाइन फ़ंक्शन के लिए किया जा सकता है!
मान लीजिए हमारे पास इस तरह का कार्य है ->
fun intercept() {
// ...
val start = SystemClock.elapsedRealtime()
val result = doSomethingWeWantToMeasure()
val duration = SystemClock.elapsedRealtime() - start
log(duration)
// ...}
यह ठीक काम करता है, लेकिन फ़ंक्शन के तर्क का मांस माप कोड से प्रदूषित हो जाता है जिससे आपके सहयोगियों के लिए यह कठिन हो जाता है कि वे क्या काम कर रहे हैं। :)
यहां बताया गया है कि इनलाइन फ़ंक्शन इस कोड की सहायता कैसे कर सकता है:
fun intercept() {
// ...
val result = measure { doSomethingWeWantToMeasure() }
// ...
}
inline fun <T> measure(action: () -> T) {
val start = SystemClock.elapsedRealtime()
val result = action()
val duration = SystemClock.elapsedRealtime() - start
log(duration)
return result
}
अब मैं माप कोड की रेखाओं पर लंघन के बिना अवरोधन () फ़ंक्शन का मुख्य उद्देश्य क्या है, इसे पढ़ने पर ध्यान केंद्रित कर सकता हूं। हम उस कोड को अन्य स्थानों पर पुन: उपयोग करने के विकल्प से भी लाभान्वित होते हैं जहाँ हम चाहते हैं
इनलाइन आपको माप (लामाडा) जैसे लंबोदर को पारित करने के बजाय एक बंद ({...}) के भीतर एक लंबो तर्क के साथ एक फ़ंक्शन को कॉल करने की अनुमति देता है