यह कोडलैब, प्रोग्रामर के लिए Kotlin बूटकैंप कोर्स का हिस्सा है. अगर कोडलैब को क्रम से पूरा किया जाता है, तो आपको इस कोर्स से सबसे ज़्यादा फ़ायदा मिलेगा. अपनी जानकारी के हिसाब से, कुछ सेक्शन को सरसरी तौर पर पढ़ा जा सकता है. यह कोर्स उन प्रोग्रामर के लिए है जिन्हें ऑब्जेक्ट ओरिएंटेड लैंग्वेज के बारे में जानकारी है और जो Kotlin सीखना चाहते हैं.
परिचय
यह Kotlin Bootcamp का आखिरी कोडलैब है. इस कोडलैब में, एनोटेशन और लेबल किए गए ब्रेक के बारे में बताया गया है. आपने Kotlin के मुख्य हिस्सों, जैसे कि लैम्ब्डा और हाई-ऑर्डर फ़ंक्शन की समीक्षा की. आपको इनलाइन फ़ंक्शन और सिंगल ऐब्स्ट्रैक्ट मेथड (एसएएम) इंटरफ़ेस के बारे में भी ज़्यादा जानकारी मिलती है. आखिर में, आपको Kotlin Standard Library के बारे में ज़्यादा जानकारी मिलेगी.
इस कोर्स में, एक सैंपल ऐप्लिकेशन बनाने के बजाय, अलग-अलग विषयों पर जानकारी दी गई है. हालांकि, ये विषय एक-दूसरे से जुड़े हुए हैं, लेकिन इन्हें इस तरह से डिज़ाइन किया गया है कि आप अपनी ज़रूरत के हिसाब से किसी भी विषय को पढ़ सकें. इन सभी उदाहरणों को एक साथ दिखाने के लिए, इनमें ऐक्वेरियम की थीम का इस्तेमाल किया गया है. अगर आपको एक्वेरियम की पूरी कहानी देखनी है, तो Udacity पर प्रोग्रामर के लिए Kotlin बूटकैंप कोर्स देखें.
आपको पहले से क्या पता होना चाहिए
- Kotlin के फ़ंक्शन, क्लास, और तरीकों का सिंटैक्स
- IntelliJ IDEA में नई क्लास बनाने और प्रोग्राम चलाने का तरीका
- Lambdas और हाई-ऑर्डर फ़ंक्शन की बुनियादी जानकारी
आपको क्या सीखने को मिलेगा
- एनोटेशन के बारे में बुनियादी जानकारी
- लेबल किए गए ब्रेक इस्तेमाल करने का तरीका
- हाई-ऑर्डर फ़ंक्शन के बारे में ज़्यादा जानकारी
- सिंगल ऐब्स्ट्रैक्ट मैथड (एसएएम) इंटरफ़ेस के बारे में जानकारी
- Kotlin Standard Library के बारे में जानकारी
आपको क्या करना होगा
- एक आसान एनोटेशन बनाएं.
- लेबल किए गए ब्रेक का इस्तेमाल करें.
- Kotlin में lambda फ़ंक्शन की समीक्षा करें.
- हाई-ऑर्डर फ़ंक्शन का इस्तेमाल करना और उन्हें बनाना.
- कुछ सिंगल ऐब्स्ट्रैक्ट मैथड इंटरफ़ेस कॉल करें.
- Kotlin स्टैंडर्ड लाइब्रेरी के कुछ फ़ंक्शन का इस्तेमाल करें.
एनोटेशन, कोड में मेटाडेटा जोड़ने का एक तरीका है. यह सिर्फ़ Kotlin के लिए नहीं है. एनोटेशन को कंपाइलर पढ़ता है और इनका इस्तेमाल कोड या लॉजिक जनरेट करने के लिए किया जाता है. Ktor और Kotlinx जैसे कई फ़्रेमवर्क, साथ ही Room, एनोटेशन का इस्तेमाल करते हैं. इससे यह कॉन्फ़िगर किया जा सकता है कि वे कैसे काम करते हैं और आपके कोड के साथ कैसे इंटरैक्ट करते हैं. फ़्रेमवर्क का इस्तेमाल शुरू करने से पहले, आपको शायद ही कोई एनोटेशन दिखे. हालांकि, एनोटेशन को पढ़ने का तरीका जानना फ़ायदेमंद होता है.
ऐसे एनोटेशन भी होते हैं जो Kotlin की स्टैंडर्ड लाइब्रेरी के ज़रिए उपलब्ध होते हैं. ये एनोटेशन, कोड को कंपाइल करने के तरीके को कंट्रोल करते हैं. अगर Kotlin को Java कोड में एक्सपोर्ट किया जा रहा है, तो ये एनोटेशन बहुत काम के होते हैं. हालांकि, ऐसा न करने पर इनकी ज़रूरत नहीं पड़ती.
एनोटेशन, एनोटेट की जाने वाली चीज़ से ठीक पहले होता है. ज़्यादातर चीज़ों को एनोटेट किया जा सकता है. जैसे, क्लास, फ़ंक्शन, तरीके, और कंट्रोल स्ट्रक्चर. कुछ एनोटेशन में आर्ग्युमेंट इस्तेमाल किए जा सकते हैं.
यहां कुछ एनोटेशन का उदाहरण दिया गया है.
@file:JvmName("InteropFish")
class InteropFish {
companion object {
@JvmStatic fun interop()
}
}इससे पता चलता है कि इस फ़ाइल का एक्सपोर्ट किया गया नाम InteropFish है और इसमें JvmName एनोटेशन है. JvmName एनोटेशन, "InteropFish" आर्ग्युमेंट ले रहा है. कंपैनियन ऑब्जेक्ट में, @JvmStatic से Kotlin को यह पता चलता है कि interop() को InteropFish में स्टैटिक फ़ंक्शन बनाना है.
आपके पास अपने एनोटेशन बनाने का विकल्प भी होता है. हालांकि, यह सुविधा ज़्यादातर तब काम आती है, जब आपको ऐसी लाइब्रेरी लिखनी हो जिसे रनटाइम के दौरान क्लास के बारे में खास जानकारी की ज़रूरत हो. इसे रिफ़्लेक्शन कहा जाता है.
पहला चरण: नया पैकेज और फ़ाइल बनाना
- src में जाकर, नया पैकेज
exampleबनाएं. - example में, नई Kotlin फ़ाइल
Annotations.ktबनाएं.
दूसरा चरण: अपना एनोटेशन बनाना
Annotations.ktमें, दो तरीकोंtrim()औरfertilize()के साथPlantक्लास बनाएं.
class Plant {
fun trim(){}
fun fertilize(){}
}- एक ऐसा फ़ंक्शन बनाएं जो किसी क्लास के सभी तरीकों को प्रिंट करे. रनटाइम के दौरान किसी क्लास के बारे में जानकारी पाने के लिए,
::classका इस्तेमाल करें. किसी क्लास के तरीकों की सूची पाने के लिए,declaredMemberFunctionsका इस्तेमाल करें. (इसे ऐक्सेस करने के लिए, आपकोkotlin.reflect.full.*इंपोर्ट करना होगा)
import kotlin.reflect.full.* // required import
class Plant {
fun trim(){}
fun fertilize(){}
}
fun testAnnotations() {
val classObj = Plant::class
for (m in classObj.declaredMemberFunctions) {
println(m.name)
}
}- अपनी टेस्ट रूटीन को कॉल करने के लिए,
main()फ़ंक्शन बनाएं. प्रोग्राम चलाएं और आउटपुट देखें.
fun main() {
testAnnotations()
}⇒ trim fertilize
- एक सामान्य एनोटेशन बनाएं,
ImAPlant.
annotation class ImAPlantइससे यह पता चलता है कि एनोटेशन किया गया है. इसके अलावा, इससे और कुछ नहीं होता.
- अपनी
Plantक्लास के सामने एनोटेशन जोड़ें.
@ImAPlant class Plant{
...
}- किसी क्लास के सभी एनोटेशन प्रिंट करने के लिए,
testAnnotations()को बदलें. किसी क्लास के सभी एनोटेशन पाने के लिए,annotationsका इस्तेमाल करें. प्रोग्राम चलाएं और नतीजे देखें.
fun testAnnotations() {
val plantObject = Plant::class
for (a in plantObject.annotations) {
println(a.annotationClass.simpleName)
}
}⇒ ImAPlant
ImAPlantएनोटेशन ढूंढने के लिए,testAnnotations()बदलें. किसी खास एनोटेशन को ढूंढने के लिए,findAnnotation()का इस्तेमाल करें. प्रोग्राम चलाएं और नतीजे देखें.
fun testAnnotations() {
val plantObject = Plant::class
val myAnnotationObject = plantObject.findAnnotation<ImAPlant>()
println(myAnnotationObject)
}
⇒ @example.ImAPlant()
तीसरा चरण: टारगेट किया गया एनोटेशन बनाना
एनोटेशन, गेटर या सेटर को टारगेट कर सकते हैं. ऐसा करने पर, @get: या @set: प्रीफ़िक्स का इस्तेमाल करके, उन्हें लागू किया जा सकता है. एनोटेशन वाले फ़्रेमवर्क का इस्तेमाल करते समय, यह समस्या अक्सर आती है.
- दो एनोटेशन,
OnGetऔरOnSetके बारे में बताएं.OnGetको सिर्फ़ प्रॉपर्टी गेटर पर लागू किया जा सकता है औरOnSetको सिर्फ़ प्रॉपर्टी सेटर पर लागू किया जा सकता है. हर एक पर@Target(AnnotationTarger.PROPERTY_GETTER)याPROPERTY_SETTERका इस्तेमाल करें.
annotation class ImAPlant
@Target(AnnotationTarget.PROPERTY_GETTER)
annotation class OnGet
@Target(AnnotationTarget.PROPERTY_SETTER)
annotation class OnSet
@ImAPlant class Plant {
@get:OnGet
val isGrowing: Boolean = true
@set:OnSet
var needsFood: Boolean = false
}एनोटेशन, ऐसी लाइब्रेरी बनाने के लिए बहुत काम के होते हैं जो रनटाइम और कभी-कभी कंपाइल टाइम, दोनों में चीज़ों की जांच करती हैं. हालांकि, सामान्य ऐप्लिकेशन कोड में सिर्फ़ फ़्रेमवर्क से मिले एनोटेशन का इस्तेमाल किया जाता है.
Kotlin में फ़्लो को कंट्रोल करने के कई तरीके हैं. आपको return के बारे में पहले से पता है. यह किसी फ़ंक्शन से उसके एनक्लोज़िंग फ़ंक्शन पर वापस जाता है. break का इस्तेमाल, return की तरह होता है. हालांकि, इसका इस्तेमाल लूप के लिए किया जाता है.
Kotlin में, लूप को कंट्रोल करने के लिए एक और तरीका उपलब्ध है. इसे लेबल वाला ब्रेक कहा जाता है. लेबल की गई break, उस लेबल से मार्क किए गए लूप के तुरंत बाद, एक्ज़ीक्यूशन पॉइंट पर पहुंच जाती है. यह खास तौर पर नेस्ट किए गए लूप के साथ काम करते समय मददगार होता है.
Kotlin में किसी भी एक्सप्रेशन को लेबल किया जा सकता है. लेबल, पहचानकर्ता के तौर पर होते हैं. इनके बाद @ का निशान होता है.
Annotations.ktमें, इनर लूप से बाहर निकलकर लेबल किए गए ब्रेक को आज़माएं.
fun labels() {
outerLoop@ for (i in 1..100) {
print("$i ")
for (j in 1..100) {
if (i > 10) break@outerLoop // breaks to outer loop
}
}
}
fun main() {
labels()
}- प्रोग्राम चलाएं और आउटपुट देखें.
⇒ 1 2 3 4 5 6 7 8 9 10 11
इसी तरह, लेबल किए गए continue का इस्तेमाल किया जा सकता है. लेबल किए गए लूप से बाहर निकलने के बजाय, लेबल किए गए continue स्टेटमेंट से लूप का अगला इटरेशन शुरू हो जाता है.
Lambdas, पहचान छिपाने वाले फ़ंक्शन होते हैं. ये ऐसे फ़ंक्शन होते हैं जिनका कोई नाम नहीं होता. इन्हें वैरिएबल को असाइन किया जा सकता है. साथ ही, इन्हें फ़ंक्शन और तरीकों के लिए आर्ग्युमेंट के तौर पर पास किया जा सकता है. ये बहुत काम के होते हैं.
पहला चरण: एक सामान्य लैम्डा फ़ंक्शन बनाना
- IntelliJ IDEA में REPL शुरू करें. इसके लिए, Tools > Kotlin > Kotlin REPL पर जाएं.
- एक ऐसा लैम्डा बनाएं जिसमें एक आर्ग्युमेंट
dirty: Intहो. यहdirty: Intको 2 से भाग देकर कैलकुलेशन करता हो.dirtylambda को वैरिएबलwaterFilterपर असाइन करें.
val waterFilter = { dirty: Int -> dirty / 2 }waterFilterको कॉल करें और वैल्यू 30 पास करें.
waterFilter(30)⇒ res0: kotlin.Int = 15
दूसरा चरण: फ़िल्टर लैंबडा बनाना
- REPL में ही, एक डेटा क्लास
Fishबनाएं. इसमें एक प्रॉपर्टीnameहो.
data class Fish(val name: String)- तीन
Fishकी एक सूची बनाओ, जिनके नाम फ़्लिपर, मोबी डिक, और डोरी हैं.
val myFish = listOf(Fish("Flipper"), Fish("Moby Dick"), Fish("Dory"))- 'i' अक्षर वाले नामों को देखने के लिए, एक फ़िल्टर जोड़ें.
myFish.filter { it.name.contains("i")}
⇒ res3: kotlin.collections.List<Line_1.Fish> = [Fish(name=Flipper), Fish(name=Moby Dick)]
लैम्डा एक्सप्रेशन में, it का मतलब मौजूदा लिस्ट एलिमेंट से है. साथ ही, फ़िल्टर को लिस्ट के हर एलिमेंट पर बारी-बारी से लागू किया जाता है.
- नतीजे में
joinString()एट्रिब्यूट की वैल्यू जोड़ें. इसके लिए,", "को सेपरेटर के तौर पर इस्तेमाल करें.
myFish.filter { it.name.contains("i")}.joinToString(", ") { it.name }
⇒ res4: kotlin.String = Flipper, Moby Dick
joinToString() फ़ंक्शन, फ़िल्टर किए गए नामों को जोड़कर एक स्ट्रिंग बनाता है. इसमें नामों को अलग करने के लिए, तय की गई स्ट्रिंग का इस्तेमाल किया जाता है. यह Kotlin की स्टैंडर्ड लाइब्रेरी में शामिल कई काम के फ़ंक्शन में से एक है.
किसी फ़ंक्शन में, lambda या किसी अन्य फ़ंक्शन को आर्ग्युमेंट के तौर पर पास करने से, हाई-ऑर्डर फ़ंक्शन बनता है. ऊपर दिया गया फ़िल्टर, इसका एक सामान्य उदाहरण है. filter() एक फ़ंक्शन है. इसमें एक लैम्डा पास किया जाता है, जो यह तय करता है कि सूची के हर एलिमेंट को कैसे प्रोसेस किया जाए.
एक्सटेंशन लैम्डा के साथ हाई-ऑर्डर फ़ंक्शन लिखना, Kotlin लैंग्वेज के सबसे मुश्किल हिस्सों में से एक है. इन्हें लिखने का तरीका सीखने में थोड़ा समय लगता है, लेकिन इनका इस्तेमाल करना बहुत आसान है.
पहला चरण: नई क्लास बनाना
- example पैकेज में, नई Kotlin फ़ाइल
Fish.ktबनाएं. Fish.ktमें, एक प्रॉपर्टीnameके साथ एक डेटा क्लासFishबनाएं.
data class Fish (var name: String)fishExamples()फ़ंक्शन बनाएं.fishExamples()में,"splashy"नाम की मछली बनाओ. सभी अक्षर छोटे होने चाहिए.
fun fishExamples() {
val fish = Fish("splashy") // all lowercase
}main()फ़ंक्शन बनाएं, जोfishExamples()को कॉल करता है.
fun main () {
fishExamples()
}- अपने प्रोग्राम को कंपाइल और चलाने के लिए,
main()की बाईं ओर मौजूद हरे रंग के त्रिकोण पर क्लिक करें. अभी कोई आउटपुट नहीं है.
दूसरा चरण: हाई-ऑर्डर फ़ंक्शन का इस्तेमाल करना
with() फ़ंक्शन की मदद से, किसी ऑब्जेक्ट या प्रॉपर्टी के एक या उससे ज़्यादा रेफ़रंस को ज़्यादा कॉम्पैक्ट तरीके से बनाया जा सकता है. this का इस्तेमाल किया जा रहा है. with() असल में एक हाई-ऑर्डर फ़ंक्शन है. लैम्डा में यह तय किया जाता है कि दिए गए ऑब्जेक्ट के साथ क्या करना है.
fishExamples()में मछली के नाम को कैपिटल लेटर में लिखने के लिए,with()का इस्तेमाल करें. कर्ली ब्रेसिज़ में,thisका मतलबwith()को पास किया गया ऑब्जेक्ट है.
fun fishExamples() {
val fish = Fish("splashy") // all lowercase
with (fish.name) {
this.capitalize()
}
}- कोई आउटपुट नहीं है, इसलिए इसके चारों ओर
println()जोड़ें. साथ ही,thisको शामिल करने की ज़रूरत नहीं है, इसलिए इसे हटाया जा सकता है.
fun fishExamples() {
val fish = Fish("splashy") // all lowercase
with (fish.name) {
println(capitalize())
}
}⇒ Splashy
तीसरा चरण: हाई-ऑर्डर फ़ंक्शन बनाना
बारीकियों के बारे में जानें, with() एक हाई-ऑर्डर फ़ंक्शन है. इसके काम करने के तरीके को समझने के लिए, with() का एक आसान वर्शन बनाया जा सकता है. यह सिर्फ़ स्ट्रिंग के लिए काम करता है.
Fish.ktमें, एक फ़ंक्शनmyWith()तय करें, जो दो आर्ग्युमेंट लेता है. आर्ग्युमेंट, वह ऑब्जेक्ट होता है जिस पर कार्रवाई करनी है. साथ ही, यह एक ऐसा फ़ंक्शन होता है जो कार्रवाई के बारे में बताता है. फ़ंक्शन के साथ आर्ग्युमेंट का नाम रखने का तरीकाblockहै. इस मामले में, यह फ़ंक्शन कुछ भी नहीं दिखाता है. इसेUnitसे दिखाया गया है.
fun myWith(name: String, block: String.() -> Unit) {}myWith() के अंदर, block() अब String का एक्सटेंशन फ़ंक्शन है. जिस क्लास को बढ़ाया जा रहा है उसे अक्सर रिसीवर ऑब्जेक्ट कहा जाता है. इसलिए, इस मामले में name रिसीवर ऑब्जेक्ट है.
myWith()के मुख्य हिस्से में, पास किए गए फ़ंक्शनblock()को रिसीवर ऑब्जेक्टnameपर लागू करें.
fun myWith(name: String, block: String.() -> Unit) {
name.block()
}fishExamples()में,with()की जगहmyWith()का इस्तेमाल करें.
fun fishExamples() {
val fish = Fish("splashy") // all lowercase
myWith (fish.name) {
println(capitalize())
}
}fish.name, नाम वाला आर्ग्युमेंट है और println(capitalize()), ब्लॉक फ़ंक्शन है.
- प्रोग्राम को चलाएं. यह पहले की तरह काम करेगा.
⇒ Splashy
चौथा चरण: ज़्यादा इनबिल्ट एक्सटेंशन एक्सप्लोर करना
with() एक्सटेंशन लैंबडा बहुत काम का होता है. यह Kotlin स्टैंडर्ड लाइब्रेरी का हिस्सा है. यहां कुछ अन्य सुझाव दिए गए हैं जो आपके काम आ सकते हैं: run(), apply(), और let().
run() फ़ंक्शन एक एक्सटेंशन है, जो सभी टाइप के साथ काम करता है. यह एक Lambda फ़ंक्शन को आर्ग्युमेंट के तौर पर लेता है और Lambda फ़ंक्शन को एक्ज़ीक्यूट करने का नतीजा दिखाता है.
fishExamples()में,fishपरrun()को कॉल करके नाम जानो.
fish.run {
name
}यह सिर्फ़ name प्रॉपर्टी दिखाता है. इसे किसी वैरिएबल को असाइन किया जा सकता है या प्रिंट किया जा सकता है. यह उदाहरण ज़्यादा काम का नहीं है, क्योंकि प्रॉपर्टी को सीधे तौर पर ऐक्सेस किया जा सकता है. हालांकि, run() ज़्यादा मुश्किल एक्सप्रेशन के लिए काम का हो सकता है.
apply() फ़ंक्शन, run() फ़ंक्शन की तरह ही होता है. हालांकि, यह लैंबडा के नतीजे के बजाय, उस बदले हुए ऑब्जेक्ट को दिखाता है जिस पर इसे लागू किया गया था. यह नए ऑब्जेक्ट पर तरीकों को कॉल करने के लिए फ़ायदेमंद हो सकता है.
fishकी कॉपी बनाएं और नई कॉपी का नाम सेट करने के लिए,apply()को कॉल करें.
val fish2 = Fish(name = "splashy").apply {
name = "sharky"
}
println(fish2.name)
⇒ sharky
let() फ़ंक्शन, apply() फ़ंक्शन की तरह ही होता है. हालांकि, यह बदलावों के साथ ऑब्जेक्ट की कॉपी दिखाता है. इससे, एक साथ कई तरह के बदलाव किए जा सकते हैं.
fishका नाम पाने के लिएlet()का इस्तेमाल करें. इसके बाद, इसे कैपिटल लेटर में बदलें. इसके साथ कोई दूसरी स्ट्रिंग जोड़ें. इसके बाद, इस स्ट्रिंग की लंबाई पता करें. लंबाई में 31 जोड़ें. इसके बाद, नतीजे को प्रिंट करें.
println(fish.let { it.name.capitalize()}
.let{it + "fish"}
.let{it.length}
.let{it + 31})⇒ 42
इस उदाहरण में, it से जुड़ा ऑब्जेक्ट टाइप Fish है. इसके बाद, String, फिर से String और आखिर में Int है.
let()को कॉल करने के बाद,fishको प्रिंट करें. आपको दिखेगा कि इसमें कोई बदलाव नहीं हुआ है.
println(fish.let { it.name.capitalize()}
.let{it + "fish"}
.let{it.length}
.let{it + 31})
println(fish)⇒ 42 Fish(name=splashy)
Lambdas और हाई-ऑर्डर फ़ंक्शन बहुत काम के होते हैं. हालांकि, आपको यह पता होना चाहिए कि lambdas ऑब्जेक्ट होते हैं. लैम्डा एक्सप्रेशन, Function इंटरफ़ेस का एक इंस्टेंस होता है. यह खुद Object का सबटाइप होता है. myWith() के पिछले उदाहरण पर ध्यान दें.
myWith(fish.name) {
capitalize()
}Function इंटरफ़ेस में एक तरीका है, invoke(), जिसे लैम्डा एक्सप्रेशन को कॉल करने के लिए बदला जाता है. इसे पूरा लिखने पर, यह कुछ इस तरह दिखेगा.
// actually creates an object that looks like this
myWith(fish.name, object : Function1<String, Unit> {
override fun invoke(name: String) {
name.capitalize()
}
})आम तौर पर, इससे कोई समस्या नहीं होती है. इसकी वजह यह है कि ऑब्जेक्ट बनाने और फ़ंक्शन कॉल करने में ज़्यादा ओवरहेड नहीं होता. इसका मतलब है कि इसमें मेमोरी और सीपीयू का समय ज़्यादा नहीं लगता. हालांकि, अगर आपको myWith() जैसी किसी ऐसी चीज़ को तय करना है जिसका इस्तेमाल हर जगह किया जाता है, तो ओवरहेड बढ़ सकता है.
Kotlin, इस मामले को हैंडल करने के लिए inline उपलब्ध कराता है. इससे कंपाइलर को थोड़ा ज़्यादा काम करना पड़ता है, लेकिन रनटाइम के दौरान ओवरहेड कम हो जाता है. (आपने पिछले लेसन में, inline के बारे में थोड़ा-बहुत जाना था. इस लेसन में, रीफ़ाइड टाइप के बारे में बताया गया था.) किसी फ़ंक्शन को inline के तौर पर मार्क करने का मतलब है कि जब भी फ़ंक्शन को कॉल किया जाएगा, कंपाइलर सोर्स कोड को "इनलाइन" फ़ंक्शन में बदल देगा. इसका मतलब है कि कंपाइलर, कोड में बदलाव करके लैंबडा को लैंबडा के अंदर दिए गए निर्देशों से बदल देगा.
अगर ऊपर दिए गए उदाहरण में myWith() को inline के तौर पर मार्क किया गया है, तो:
inline myWith(fish.name) {
capitalize()
}इसे सीधे तौर पर कॉल में बदल दिया जाता है:
// with myWith() inline, this becomes
fish.name.capitalize()ध्यान दें कि बड़े फ़ंक्शन को इनलाइन करने से, आपके कोड का साइज़ बढ़ जाता है. इसलिए, इसका इस्तेमाल उन आसान फ़ंक्शन के लिए सबसे अच्छा होता है जिनका इस्तेमाल कई बार किया जाता है, जैसे कि myWith(). जिन लाइब्रेरी के बारे में आपने पहले जाना था उनके एक्सटेंशन फ़ंक्शन को inline के तौर पर मार्क किया गया है. इसलिए, आपको अतिरिक्त ऑब्जेक्ट बनाए जाने के बारे में चिंता करने की ज़रूरत नहीं है.
सिंगल एब्सट्रैक्ट मैथड का मतलब सिर्फ़ एक ऐसा इंटरफ़ेस होता है जिसमें एक ही मैथड होता है. Java प्रोग्रामिंग लैंग्वेज में लिखे गए एपीआई का इस्तेमाल करते समय, ये बहुत आम हैं. इसलिए, इसके लिए एक संक्षिप्त नाम है, एसएएम. इसके कुछ उदाहरण Runnable हैं, जिसमें एक ही ऐब्स्ट्रैक्ट मैथड run() है. इसके अलावा, Callable में भी एक ही ऐब्स्ट्रैक्ट मैथड call() है.
Kotlin में, आपको ऐसे फ़ंक्शन को हमेशा कॉल करना होता है जो SAM को पैरामीटर के तौर पर लेते हैं. यहाँ दिया गया उदाहरण आज़माएँ.
- example में,
JavaRunनाम की एक Java क्लास बनाएं और फ़ाइल में यह कोड चिपकाएं.
package example;
public class JavaRun {
public static void runNow(Runnable runnable) {
runnable.run();
}
}Kotlin में, object: को टाइप से पहले रखकर, इंटरफ़ेस लागू करने वाले ऑब्जेक्ट को इंस्टैंटिएट किया जा सकता है. यह एसएएम को पैरामीटर पास करने के लिए उपयोगी है.
Fish.ktमें वापस जाकर, एक फ़ंक्शनrunExample()बनाएं. यह फ़ंक्शन,object:का इस्तेमाल करकेRunnableबनाता है. ऑब्जेक्ट कोrun()लागू करना चाहिए. इसके लिए,"I'm a Runnable"प्रिंट करें.
fun runExample() {
val runnable = object: Runnable {
override fun run() {
println("I'm a Runnable")
}
}
}- आपने जो ऑब्जेक्ट बनाया है उसकी मदद से,
JavaRun.runNow()को कॉल करें.
fun runExample() {
val runnable = object: Runnable {
override fun run() {
println("I'm a Runnable")
}
}
JavaRun.runNow(runnable)
}main()सेrunExample()को कॉल करें और प्रोग्राम चलाएं.
⇒ I'm a Runnable
किसी चीज़ को प्रिंट करने के लिए बहुत काम करना पड़ता है. हालांकि, यह इस बात का अच्छा उदाहरण है कि SAM कैसे काम करता है. बेशक, Kotlin में ऐसा करने का एक आसान तरीका है. इस कोड को ज़्यादा छोटा बनाने के लिए, ऑब्जेक्ट की जगह लैंबडा का इस्तेमाल करें.
runExampleमें मौजूद कोड को हटाएं. इसे लैम्डा के साथrunNow()को कॉल करने के लिए बदलें. इसके बाद, प्रोग्राम चलाएं.
fun runExample() {
JavaRun.runNow({
println("Passing a lambda as a Runnable")
})
}
⇒ Passing a lambda as a Runnable
- आखिरी पैरामीटर कॉल सिंटैक्स का इस्तेमाल करके, इसे और छोटा बनाया जा सकता है. साथ ही, कोष्ठकों को हटाया जा सकता है.
fun runExample() {
JavaRun.runNow {
println("Last parameter is a lambda as a Runnable")
}
}⇒ Last parameter is a lambda as a Runnable
यह एसएएम यानी सिंगल एब्सट्रैक्ट मैथड की बुनियादी जानकारी है. पैटर्न:Class.singleAbstractMethod { lambda_of_override } का इस्तेमाल करके, एक लाइन के कोड से एसएएम को इंस्टैंशिएट, ओवरराइड, और कॉल किया जा सकता है
इस लेसन में, हमने लैम्डा के बारे में जाना. साथ ही, Kotlin के मुख्य हिस्सों में से एक, हाई-ऑर्डर फ़ंक्शन के बारे में ज़्यादा जानकारी हासिल की. आपने एनोटेशन और लेबल किए गए ब्रेक के बारे में भी जाना.
- कंपाइलर को जानकारी देने के लिए, एनोटेशन का इस्तेमाल करें. उदाहरण के लिए:
@file:JvmName("Foo") - नेस्ट किए गए लूप से बाहर निकलने के लिए, लेबल किए गए ब्रेक का इस्तेमाल करें. उदाहरण के लिए:
if (i > 10) break@outerLoop // breaks to outerLoop label - Lambdas, हाई-ऑर्डर फ़ंक्शन के साथ मिलकर बहुत असरदार हो सकते हैं.
- लैम्ब्डा, ऑब्जेक्ट होते हैं. ऑब्जेक्ट बनाने से बचने के लिए, फ़ंक्शन को
inlineके साथ मार्क किया जा सकता है. इससे कंपाइलर, lambda के कॉन्टेंट को सीधे कोड में डाल देगा. inlineका इस्तेमाल सावधानी से करें. हालांकि, इससे आपके प्रोग्राम के लिए संसाधन के इस्तेमाल को कम करने में मदद मिल सकती है.- एसएएम (सिंगल एब्सट्रैक्ट मैथड) एक सामान्य पैटर्न है. लैम्ब्डा की मदद से इसे आसान बनाया गया है. इसका बेसिक पैटर्न यह है:
Class.singleAbstractMethod { lamba_of_override } - Kotlin Standard Library में कई काम के फ़ंक्शन उपलब्ध हैं. इनमें कई एसएएम भी शामिल हैं. इसलिए, इसके बारे में जानें.
इस कोर्स में Kotlin के बारे में बहुत कुछ नहीं बताया गया है. हालांकि, अब आपके पास Kotlin प्रोग्राम डेवलप करने के लिए बुनियादी जानकारी है. हमें उम्मीद है कि आपको यह एक्सप्रेसिव लैंग्वेज पसंद आई होगी. साथ ही, आपको कम कोड लिखकर ज़्यादा फ़ंक्शन बनाने में मज़ा आएगा. खास तौर पर, अगर आपने Java प्रोग्रामिंग लैंग्वेज का इस्तेमाल किया है. Kotlin में विशेषज्ञ बनने का सबसे अच्छा तरीका है कि आप इसका इस्तेमाल करते रहें और इसके बारे में सीखते रहें. इसलिए, Kotlin के बारे में खुद से एक्सप्लोर करना और सीखना जारी रखें.
Kotlin का दस्तावेज़
अगर आपको इस कोर्स के किसी विषय के बारे में ज़्यादा जानकारी चाहिए या आपको कोई समस्या आ रही है, तो https://kotlinlang.org पर जाएं.
Kotlin के ट्यूटोरियल
https://try.kotlinlang.org वेबसाइट पर, Kotlin Koans नाम के रिच ट्यूटोरियल, वेब पर आधारित इंटरप्रेटर, और उदाहरणों के साथ रेफ़रंस दस्तावेज़ों का पूरा सेट शामिल है.
Udacity कोर्स
इस विषय पर Udacity का कोर्स देखने के लिए, Kotlin Bootcamp for Programmers पर जाएं.
IntelliJ IDEA
IntelliJ IDEA के लिए दस्तावेज़, JetBrains की वेबसाइट पर उपलब्ध हैं.
Kotlin स्टैंडर्ड लाइब्रेरी
Kotlin स्टैंडर्ड लाइब्रेरी में कई काम के फ़ंक्शन मौजूद होते हैं. अपना फ़ंक्शन या इंटरफ़ेस लिखने से पहले, हमेशा स्टैंडर्ड लाइब्रेरी देखें. इससे आपको पता चलेगा कि क्या किसी ने आपके लिए कुछ काम सेव किया है. समय-समय पर देखते रहें, क्योंकि नई सुविधाएं अक्सर जोड़ी जाती हैं.
Kotlin के ट्यूटोरियल
https://try.kotlinlang.org वेबसाइट पर, Kotlin Koans नाम के रिच ट्यूटोरियल, वेब पर आधारित इंटरप्रेटर, और उदाहरणों के साथ रेफ़रंस दस्तावेज़ों का पूरा सेट शामिल है.
Udacity कोर्स
इस विषय पर Udacity का कोर्स देखने के लिए, Kotlin Bootcamp for Programmers पर जाएं.
IntelliJ IDEA
IntelliJ IDEA के लिए दस्तावेज़, JetBrains की वेबसाइट पर उपलब्ध हैं.
इस सेक्शन में, उन छात्र-छात्राओं के लिए होमवर्क असाइनमेंट की सूची दी गई है जो किसी शिक्षक के कोर्स के हिस्से के तौर पर इस कोडलैब पर काम कर रहे हैं. शिक्षक के पास ये विकल्प होते हैं:
- अगर ज़रूरी हो, तो होमवर्क असाइन करें.
- छात्र-छात्राओं को बताएं कि होमवर्क असाइनमेंट कैसे सबमिट किए जाते हैं.
- होमवर्क असाइनमेंट को ग्रेड दें.
शिक्षक इन सुझावों का इस्तेमाल अपनी ज़रूरत के हिसाब से कर सकते हैं. साथ ही, वे चाहें, तो कोई दूसरा होमवर्क भी दे सकते हैं.
अगर आपको यह कोडलैब खुद से पूरा करना है, तो अपनी जानकारी की जांच करने के लिए, इन होमवर्क असाइनमेंट का इस्तेमाल करें.
इन सवालों के जवाब दें
पहला सवाल
Kotlin में, SAM का मतलब है:
▢ Safe Argument Matching
▢ ऐक्सेस करने का आसान तरीका
▢ सिंगल एब्सट्रैक्ट मैथड
▢ रणनीति के हिसाब से ऐक्सेस करने का तरीका
दूसरा सवाल
इनमें से कौनसा Kotlin स्टैंडर्ड लाइब्रेरी एक्सटेंशन फ़ंक्शन नहीं है?
▢ elvis()
▢ apply()
▢ run()
▢ with()
तीसरा सवाल
Kotlin में लैम्डा के बारे में इनमें से कौनसी बात सही नहीं है?
▢ लैम्डा, पहचान छिपाने वाले फ़ंक्शन होते हैं.
▢ लैम्ब्डा, ऑब्जेक्ट होते हैं. हालांकि, इन्हें इनलाइन किया जा सकता है.
▢ लैम्ब्डा में बहुत ज़्यादा संसाधनों की ज़रूरत होती है. इसलिए, इनका इस्तेमाल नहीं किया जाना चाहिए.
▢ लैम्ब्डा को अन्य फ़ंक्शन में पास किया जा सकता है.
चौथा सवाल
Kotlin में लेबल को एक आइडेंटिफ़ायर से दिखाया जाता है. इसके बाद:
▢ :
▢ ::
▢ @:
▢ @
बधाई हो! आपने प्रोग्रामर के लिए Kotlin Bootcamp कोडलैब पूरा कर लिया है.
कोर्स की खास जानकारी और अन्य कोडलैब के लिंक देखने के लिए, "प्रोग्रामर के लिए Kotlin बूटकैंप: कोर्स में आपका स्वागत है." लेख पढ़ें