extension property — Kotlin की एक तंत्र जो मौजूदा क्लासेज़ में नए गुण जोड़ने की अनुमति देता है बिना इनहेरिटेंस और बिना सोर्स कोड बदले। extension functions के विपरीत, extension properties स्थिति संग्रहीत नहीं कर सकतीं — वे केवल getter के साथ और वैकल्पिक रूप से setter के साथ घोषित की जाती हैं, क्योंकि उनके पास backing field नहीं होता। Kotlin Documentation, 2025 के अनुसार, extension properties स्टैटिक getter और setter विधियों में संकलित होती हैं जिनमें receiver पहला पैरामीटर होता है।
मुख्य बिंदु
Extension property Kotlin में एक सिंटैक्टिक संरचना है जो मौजूदा प्रकार में उसकी घोषणा बदले बिना एक गुण जोड़ती है। गुण को receiver type के साथ घोषित किया जाता है और इसमें getter होना चाहिए। मुख्य अंतर सामान्य गुणों से — backing field की अनुपस्थिति: extension property डेटा संग्रहीत नहीं कर सकती, केवल receiver ऑब्जेक्ट के आधार पर गणना कर सकती है।
Kotlin Foundation Survey (2024) के अनुसार, extension properties extension functions की तुलना में कम लोकप्रिय हैं — लगभग 45% डेवलपर इन्हें नियमित रूप से उपयोग करते हैं। यह स्थिति की कमी की सीमा के कारण है, जो अनुप्रयोग के दायरे को संकुचित करता है। फिर भी, गणना किए गए गुणों के लिए जो तार्किक रूप से एक प्रकार से बंधे हैं, extension properties सबसे संक्षिप्त विकल्प हैं।
Extension properties स्टैटिक getter और setter विधियों की एक जोड़ी में संकलित होती हैं। बाइटकोड स्तर पर, extension property और extension function को कॉल करने में कोई अंतर नहीं है — दोनों receiver पैरामीटर के साथ स्टैटिक विधियाँ बन जाती हैं। JetBrains (Kotlin Docs, 2025) के अनुसार, कोई ओवरहेड नहीं है।
छोटी गणना की गई मानों के लिए extension properties का उपयोग करें जो गुणों की तरह दिखनी चाहिए न कि विधि कॉल की तरह — इससे कोड पठनीयता में सुधार होता है और एकसमान पहुँच सिद्धांत का पालन होता है।
Extension property घोषित करने के लिए, सामान्य गुण के समान सिंटैक्स का उपयोग करें, लेकिन receiver type उपसर्ग के साथ। val अनिवार्य getter के साथ केवल-पढ़ने योग्य extension property घोषित करता है, var getter और वैकल्पिक setter के साथ परिवर्तनशील घोषित करता है।
// केवल-पढ़ने योग्य extension property
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// कॉल
val valid = "test@test.com".isEmail
ध्यान दें: extension property को कोष्ठक के बिना बुलाया जाता है — str.isEmail, str.isEmail() नहीं। यह extension property और extension function के बीच मुख्य अंतर है: गुण एक फ़ील्ड की तरह दिखता है, हालाँकि वास्तव में यह getter के माध्यम से गणना किया जाता है।
Extension properties जेनेरिक हो सकती हैं — receiver जेनेरिक प्रकार पैरामीटर का उपयोग कर सकता है। यह सार्वभौमिक गुण बनाने की अनुमति देता है जो किसी भी संग्रह प्रकार के साथ काम करते हैं।
val List<T>.secondOrNull: T?
get() = if (size >= 2) this[1] else null
val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"
secondOrNull गुण किसी भी प्रकार T के लिए काम करता है, सूची का दूसरा तत्व लौटाता है या null यदि दो से कम तत्व हों। यह एक विशिष्ट उदाहरण है जहाँ extension property फ़ंक्शन से अधिक उपयुक्त है — इसका उपयोग फ़ील्ड पढ़ने जैसा दिखता है।
Extension property में backing field नहीं हो सकता क्योंकि यह क्लास मेटाडेटा में नहीं जोड़ा जाता — यह केवल स्टैटिक getter/setter फ़ंक्शन की जोड़ी के रूप में मौजूद होता है। Backing field (Kotlin में field कीवर्ड) क्लास का एक आंतरिक फ़ील्ड है जो गुण का मान संग्रहीत करता है। Extension property के पास क्लास की आंतरिक संरचना तक पहुँच नहीं है।
// ❌ त्रुटि: extension property में backing field नहीं हो सकता
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // फ़ील्ड सुलभ नहीं है!
}
// ✅ सही: बाहरी भंडारण का उपयोग करें
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
एक बाहरी Map उदाहरण में भंडारण समस्या हल करती है लेकिन दूसरी समस्या पैदा करती है — मेमोरी लीक। Extension property के माध्यम से प्राप्त मान Map में हमेशा रहते हैं यदि साफ न किए जाएँ। यह सीमा extension properties को कैशिंग या अस्थायी डेटा संग्रहीत करने के लिए अनुपयुक्त बनाती है।
कैशिंग के लिए, WeakHashMap या स्वचालित सफाई वाले तंत्र का उपयोग करने की अनुशंसा की जाती है। JetBrains जीवनचक्र प्रबंधन के बिना उत्पादन कोड में बाहरी भंडारण के साथ var extension properties के उपयोग से बचने की सलाह देता है।
Extension property और extension function के बीच चुनाव शब्दार्थ पर निर्भर करता है: गुण किसी वस्तु की विशेषता का वर्णन करता है, जबकि फ़ंक्शन एक क्रिया का वर्णन करता है। एकसमान पहुँच सिद्धांत कहता है: क्लाइंट को यह नहीं जानना चाहिए कि मान गणना किया गया है या संग्रहीत। यदि मान को विशेषता के रूप में प्रस्तुत किया जा सकता है (लंबाई, आकार, स्थिति) — गुण का उपयोग करें।
| मापदंड | Extension property | Extension function |
|---|---|---|
| कॉल | बिना कोष्ठक: obj.property | कोष्ठक के साथ: obj.function() |
| शब्दार्थ | विशेषता, गुण | क्रिया, संचालन |
| Backing field | समर्थित नहीं | लागू नहीं |
| पैरामीटर | केवल getter/setter | कोई भी पैरामीटर |
| प्रदर्शन | समान (स्टैटिक विधि) | समान (स्टैटिक विधि) |
| उदाहरण | text.length | text.isEmail() |
नियम सरल है: यदि संचालन पैरामीटर लेता है — extension function का उपयोग करें। यदि यह बिना पैरामीटर के सरल गणना मान है — extension property का उपयोग करें। Android Architecture Guide (Google, 2025) के अनुसार, डेटा तक पहुँच के लिए extension properties और साइड इफ़ेक्ट वाले संचालन के लिए extension functions को प्राथमिकता दी जानी चाहिए।
var कीवर्ड के साथ extension property setter का समर्थन करती है, लेकिन मान संग्रहीत करने की क्षमता के बिना — setter आमतौर पर साइड इफ़ेक्ट करता है या डेटा बाहरी भंडारण में सहेजता है। सिंटैक्स परिवर्तनशील क्लास गुणों के समान है।
// setter के साथ परिवर्तनशील extension property
var StringBuilder.lastChar: Char
get() = this[length - 1]
set(value) {
this.setCharAt(length - 1, value)
}
val sb = StringBuilder("Kotlin")
println(sb.lastChar) // n
sb.lastChar = '!'
println(sb) // Kotli!
lastChar गुण Kotlin दस्तावेज़ीकरण का एक क्लासिक उदाहरण है। Getter StringBuilder का अंतिम अक्षर लौटाता है, setter इसे एक नए मान से बदल देता है। ध्यान दें: स्थिति स्वयं StringBuilder में संग्रहीत है (setCharAt के माध्यम से), न कि अलग फ़ील्ड में — यह extension property का सही उपयोग है।
वास्तविक परियोजनाओं में, extension properties का उपयोग अक्सर संग्रह डेटा तक पहुँच को सरल बनाने, UI तत्वों के आकार या स्थिति की गणना करने, और मौजूदा क्लासेज़ के ऊपर सुविधाजनक API बनाने के लिए किया जाता है। Kotlin मानक पुस्तकालय इस तंत्र का सक्रिय रूप से उपयोग करता है: संग्रह के लिए size, indices, lastIndex — ये extension properties हैं।
// संग्रह के लिए extension properties
val List<Int>.sumFast: Int
get() = fold(0) { acc, i -> acc + i }
val String.half: String
get() = this.substring(0, length / 2)
// Android View के लिए extension property
val View.isVisible: Boolean
get() = visibility == View.VISIBLE
// सुरक्षित receiver के माध्यम से शून्य जाँच
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
View के लिए extension property isVisible — एक उदाहरण जो हर Android डेवलपर को जानना चाहिए। view.visibility == View.VISIBLE के बजाय आप view.isVisible लिख सकते हैं। यह न केवल छोटा है, बल्कि प्राकृतिक भाषा की तरह पढ़ा जाता है: «यदि view दृश्य है»। सरलता के बावजूद, ऐसे गुण कोड पठनीयता में काफी सुधार करते हैं।
अक्सर पूछे जाने वाले प्रश्न
नहीं, extension properties को companion object या object declaration के लिए घोषित नहीं किया जा सकता। एक्सटेंशन तंत्र केवल क्लासेज़, इंटरफ़ेस और nullable प्रकारों पर लागू होता है। object के लिए, सामान्य शीर्ष-स्तरीय फ़ंक्शन का उपयोग करें।
Inline गुण (inline मॉडिफ़ायर के साथ) — Kotlin का एक तंत्र है जो गुण ऑब्जेक्ट बनाए बिना getter/setter को कॉल करता है। Extension property हमेशा स्टैटिक विधि में संकलित होती है, जबकि inline गुण बिना आवरण के कॉल में संकलित होता है। वे अलग-अलग समस्याएँ हल करते हैं: extension property मौजूदा प्रकार में गुण जोड़ती है, inline — अपने स्वयं के गुणों के कॉल को अनुकूलित करती है।
हाँ, extension property में एनोटेशन हो सकते हैं, लेकिन केवल घोषणा स्तर पर। सामान्य क्लास गुणों के विपरीत, extension property के getter या setter को अलग से एनोटेट नहीं किया जा सकता। उदाहरण: @JvmName("getIsValid") val String.isValid get() = true.
नहीं, extension properties को companion object के साथ receiver के रूप में घोषित नहीं किया जा सकता। यह भाषा की एक सीमा है — extension property केवल प्रकार के इंस्टेंस के साथ काम करती है, जबकि companion object एक स्टैटिक संदर्भ है। शीर्ष-स्तरीय extension फ़ंक्शन या स्थिरांक का उपयोग करें।
न्यूनतम. प्रत्येक extension property संकलित बाइटकोड में एक स्टैटिक getter विधि (और वैकल्पिक रूप से setter) जोड़ती है। तुलना के लिए, समान गुण वाला रैपर क्लास बनाना एक पूरा क्लास जोड़ता है। Extension properties कार्यक्षमता बढ़ाने का एक हल्का दृष्टिकोण है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें