extension function — Kotlin का एक तंत्र जो मौजूदा क्लासेज़ में बिना इनहेरिटेंस और बिना सोर्स कोड बदले नए मेथड जोड़ने की अनुमति देता है। फंक्शन को रिसीवर प्रकार के उपसर्ग के साथ घोषित किया जाता है और उस प्रकार की सामान्य विधि की तरह कॉल किया जाता है। Kotlin Documentation, 2025 के अनुसार, extension functions को पहले पैरामीटर के रूप में रिसीवर के साथ स्टैटिक मेथड में संकलित किया जाता है, जो सामान्य कॉल की तुलना में रनटाइम पर शून्य overhead की गारंटी देता है।
मुख्य बातें
Extension function एक फंक्शन है जो क्लास के बाहर घोषित किया जाता है लेकिन उसकी विधि के रूप में कॉल किया जाता है। यह एक रिसीवर प्रकार लेता है जिसमें नई विधि जोड़ी जाती है। फंक्शन के अंदर, कीवर्ड this रिसीवर प्रकार के इंस्टेंस को संदर्भित करता है। यह दृष्टिकोण अंतिम क्लासेज़, तृतीय-पक्ष लाइब्रेरी क्लासेज़ और यहां तक कि आदिम प्रकारों को बिना रैपर बनाए विस्तारित करने की अनुमति देता है।
Java के विपरीत, जहां मौजूदा क्लास में मेथड जोड़ने के लिए या तो इनहेरिटेंस या स्टैटिक यूटिलिटी क्लास की आवश्यकता होती है, Kotlin बिना boilerplate के एक सुंदर समाधान प्रदान करता है। Kotlin Foundation अध्ययन (2024) के अनुसार, extension functions भाषा की पाँच सबसे अधिक उपयोग की जाने वाली सुविधाओं में से हैं — 78% Kotlin डेवलपर अपने दैनिक कार्य में इनका उपयोग करते हैं।
Kotlin कंपाइलर extension function को एक स्टैटिक मेथड में अनुवादित करता है जहाँ रिसीवर इंस्टेंस को पहले आर्गुमेंट के रूप में पारित किया जाता है। इसका मतलब है कि extension functions लक्ष्य क्लास के बाइटकोड को संशोधित नहीं करते हैं और एनकैप्सुलेशन को नहीं तोड़ते हैं — केवल रिसीवर के सार्वजनिक फ़ील्ड और मेथड ही सुलभ हैं।
स्वच्छ उपयोगिता फंक्शन लिखने के लिए extension functions का उपयोग करें जो तार्किक रूप से एक विशिष्ट प्रकार से बंधे हों लेकिन उसके स्रोत कोड में नहीं जोड़े जा सकते।
Extension function का मूल सिंटैक्स: रिसीवर प्रकार का नाम, एक डॉट, फंक्शन का नाम, फिर पैरामीटर और रिटर्न प्रकार। फंक्शन के अंदर, रिसीवर this के माध्यम से सुलभ है।
// Extension function for String
fun String.isEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// Called as regular String method
val result = "user@example.com".isEmail() // true
इस उदाहरण में, isEmail() सभी स्ट्रिंग के लिए उपलब्ध हो जाता है। फंक्शन के अंदर, this उस स्ट्रिंग को संदर्भित करता है जिस पर मेथड कॉल किया जाता है। Kotlin अधिकांश मामलों में this को छोड़ने की अनुमति देता है — आप this.contains("@") के बजाय केवल contains("@") लिख सकते हैं।
Extension functions अतिरिक्त पैरामीटर स्वीकार कर सकते हैं और किसी भी प्रकार के मान लौटा सकते हैं। यह उन्हें पूर्ण फंक्शन बनाता है, न कि केवल सिंटैक्टिक शुगर।
fun List<Int>.defaultIfEmpty(default: Int): List<Int> {
if (this.isEmpty()) return listOf(default)
return this
}
val populated = listOf(1, 2).defaultIfEmpty(0)
val empty = listOf<Int>().defaultIfEmpty(0)
default पैरामीटर खाली सूची के लिए लौटाए गए मान को परिभाषित करता है। Extension function जेनेरिक हो सकता है — List
Kotlin में extension functions स्टैटिक डिस्पैच का उपयोग करते हैं, वर्चुअल डिस्पैच का नहीं। यह सामान्य क्लास मेथड से एक महत्वपूर्ण अंतर है। कौन सी extension function कॉल की जाएगी यह कंपाइल समय पर वेरिएबल के स्टैटिक प्रकार द्वारा निर्धारित किया जाता है, न कि उसके वास्तविक रनटाइम प्रकार द्वारा।
open class Animal
class Dog : Animal()
fun Animal.speak() = "Animal sound"
fun Dog.speak() = "Woof"
fun test() {
val animal: Animal = Dog()
println(animal.speak()) // "Animal sound" — static type Animal
val dog: Dog = Dog()
println(dog.speak()) // "Woof" — static type Dog
}
भले ही animal वेरिएबल Dog के इंस्टेंस की ओर इशारा करता है, Animal के लिए extension function कॉल किया जाता है क्योंकि वेरिएबल का स्टैटिक प्रकार Animal है। यदि speak() एक वर्चुअल क्लास मेथड होता, तो Dog.speak() कॉल किया जाता। यह व्यवहार extension functions के साथ API डिज़ाइन करते समय ध्यान में रखना महत्वपूर्ण है।
Extension functions क्लास के सदस्य नहीं हैं — ये सामान्य फंक्शन हैं जिन्हें दूसरी फ़ाइल में उपयोग करने के लिए इंपोर्ट की आवश्यकता होती है। Kotlin इंपोर्ट के दो विकल्प प्रदान करता है: फंक्शन नाम से या नाम बदलकर।
// Import by name
import com.example.extensions.isEmail
// Import with alias (to resolve conflicts)
import com.example.extensions.isEmail as isValidEmail
// Call after import
val valid = "test@test.com".isEmail()
as के माध्यम से नाम बदलना नाम विरोध के मामलों में उपयोगी है — उदाहरण के लिए, यदि दो लाइब्रेरी एक ही प्रकार के लिए समान नाम वाली extension function प्रदान करती हैं। इस मामले में, आप उनमें से एक को अलग नाम से इंपोर्ट कर सकते हैं और नए नाम का उपयोग करके कॉल कर सकते हैं।
Extension functions को विभिन्न स्तरों पर घोषित किया जा सकता है:
| स्तर | दृश्यता | उदाहरण |
|---|---|---|
| Top-level | इंपोर्ट के बाद पूरा प्रोजेक्ट | fun String.isEmail() |
| Member extension | मालिक क्लास के अंदर | class A { fun B.ext() } |
| Local | फंक्शन के अंदर | fun test() { fun String.ext() } |
Member extension functions एक विशेष मामला है जहाँ extension function दूसरी क्लास के अंदर घोषित किया जाता है। इस मामले में, extension function के अंदर रिसीवर (फंक्शन का this) और बाहरी क्लास के सदस्य दोनों सुलभ हैं।
यदि किसी क्लास में extension function के समान हस्ताक्षर वाला मेथड है, तो क्लास सदस्य हमेशा कॉल किया जाता है। Extension function कभी भी क्लास मेथड को ओवरराइड नहीं करता — यह आकस्मिक ओवरराइड को रोकने के लिए एक आर्किटेक्चरल निर्णय है।
class User {
fun greet() = "Hello from class"
}
fun User.greet() = "Hello from extension"
fun main() {
val user = User()
println(user.greet()) // "Hello from class"
}
भले ही extension function बाद में परिभाषित किया गया हो और उसका हस्ताक्षर समान हो, कंपाइलर क्लास मेथड का चयन करेगा। Kotlin कंपाइलर ऐसी स्थिति का पता चलने पर चेतावनी जारी करता है। क्लास मेथड मौजूद होने पर extension function को कॉल करने का एकमात्र तरीका इसे सामान्य फंक्शन के रूप में कॉल करना है: greet(user).
Android डेवलपमेंट में, extension functions View, Context और fragments के साथ काम करने के लिए एक मानक उपकरण बन गए हैं। Android KTX लाइब्रेरी extension functions पर बनी है, जो Android API पर सुविधाजनक रैपर प्रदान करती है।
// Extension function for working with View
fun View.show() {
visibility = View.VISIBLE
}
fun View.hide() {
visibility = View.GONE
}
// Extension function for Context — toast
fun Context.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
// Extension function as DSL builder
fun String.colorFormat(color: String): String =
"$color$this\u001b[0m"
toast() extension function Context-निर्भर कॉल को संक्षिप्त बनाता है: Toast.makeText(context, message, length).show() लिखने के बजाय, बस context.toast("पाठ") लिखना पर्याप्त है। यह boilerplate को कम करता है और कोड को अधिक पठनीय बनाता है।
अक्सर पूछे जाने वाले प्रश्न
नहीं, extension functions स्टैटिक डिस्पैच का उपयोग करते हैं। यदि आप बेस क्लास के लिए और उपवर्ग के लिए समान extension function घोषित करते हैं, तो कौन सा कॉल किया जाएगा यह कंपाइल समय पर वेरिएबल के स्टैटिक प्रकार द्वारा निर्धारित होता है, न कि वास्तविक रनटाइम प्रकार द्वारा।
आप nullable रिसीवर प्रकारों के लिए extension functions घोषित कर सकते हैं: fun String?.isNullOrEmail(). ऐसे फंक्शन के अंदर, this null हो सकता है, इसलिए आपको सुरक्षित कॉल ऑपरेटर या स्पष्ट null जांच का उपयोग करना चाहिए।
नहीं, extension functions स्टैटिक मेथड में संकलित होते हैं। बाइटकोड स्तर पर, extension function को कॉल करना पहले पैरामीटर के रूप में रिसीवर के साथ स्टैटिक मेथड को कॉल करने के समान है। कोई रिफ्लेक्शन या डायनामिक डिस्पैच शामिल नहीं है।
हाँ, extension properties extension functions के समान काम करती हैं लेकिन स्थिति संग्रहीत नहीं कर सकतीं — केवल getter और setter। उदाहरण के लिए: val List
Java में आप StringUtils.isEmail(str) लिखते हैं, जबकि Kotlin में आप str.isEmail() लिखते हैं। अंतर केवल सिंटैक्स का नहीं है: extension functions IDE में ऑटोकम्प्लीट का समर्थन करते हैं, कॉल चेन की पठनीयता में सुधार करते हैं, और IDE को किसी विशिष्ट प्रकार के लिए प्रासंगिक फंक्शन सुझाने की अनुमति देते हैं। Java में ये क्षमताएँ नहीं हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें