Kotlin में 'by' कीवर्ड क्या करता है?


90

एंड्रॉइड के लिए विकसित करते समय मैं कभी-कभी कुछ ऐसा होता है जो इस तरह दिखता है:

var someModel: someViewModel by notNullAndObservable { vm ->
  ...
}

मुझे समझ नहीं आया कि byकीवर्ड का महत्व क्या है।


जवाबों:


76

में Kotlin संदर्भ आप के लिए दो का उपयोग करता है मिलेगा by, पहले किया जा रहा है प्रत्यायोजित गुण जो उपयोग आप ऊपर है:

कुछ सामान्य प्रकार के गुण हैं, हालांकि, हम उन्हें मैन्युअल रूप से लागू कर सकते हैं हर बार जब हमें उनकी आवश्यकता होती है, तो एक बार और सभी के लिए लागू करना बहुत अच्छा होगा, और एक पुस्तकालय में डाल दिया जाएगा। उदाहरणों में आलसी गुण शामिल हैं: मूल्य केवल पहली पहुंच, अवलोकन योग्य गुणों पर गणना किया जाता है: श्रोताओं को इस संपत्ति में परिवर्तन के बारे में सूचित किया जाता है, गुणों को मानचित्र में संग्रहीत करते हुए, प्रत्येक अलग क्षेत्र में नहीं।

यहां आप गेट्टर / सेटर को दूसरे वर्ग को सौंपते हैं जो काम करता है और इसमें सामान्य कोड हो सकता है। एक अन्य उदाहरण के रूप में, कोटलिन के लिए निर्भरता इंजेक्टर में से कुछ इस मॉडल को निर्भरता इंजेक्शन इंजन द्वारा प्रबंधित इंस्टेंस की एक रजिस्ट्री से मूल्य प्राप्त करने के लिए इस मॉडल का समर्थन करते हैं।

और इंटरफ़ेस / कक्षा प्रतिनिधिमंडल अन्य उपयोग है:

डेलिगेशन पैटर्न विरासत को लागू करने के लिए एक अच्छा विकल्प साबित हुआ है, और कोटलिन इसे मूल रूप से शून्य बॉयलरप्लेट कोड की आवश्यकता का समर्थन करता है। व्युत्पन्न एक वर्ग एक इंटरफ़ेस बेस से विरासत में मिल सकता है और अपने सभी सार्वजनिक तरीकों को एक निर्दिष्ट ऑब्जेक्ट में सौंप सकता है

यहां आप किसी अन्य कार्यान्वयन के लिए एक इंटरफ़ेस को सौंप सकते हैं इसलिए कार्यान्वयन वर्ग को केवल उस चीज़ को ओवरराइड करने की आवश्यकता है जिसे वह बदलना चाहता है, जबकि बाकी विधियां एक पूर्ण कार्यान्वयन पर वापस सौंपती हैं।

एक जीवंत उदाहरण क्लाटर रीडॉनली / इम्यूटेबल संग्रह होगा जहां वे वास्तव में विशिष्ट संग्रह इंटरफ़ेस को किसी अन्य वर्ग में सौंपते हैं और फिर कुछ भी ओवरराइड करते हैं जो कि आसानी से कार्यान्वयन में अलग होना चाहिए। बहुत सारे कार्यों को सहेजना मैन्युअल रूप से अन्य सभी तरीकों को नहीं सौंपना है।

इन दोनों को कोटलिन भाषा के संदर्भ द्वारा कवर किया गया है , भाषा के आधार विषयों के लिए वहां शुरू करते हैं।


93

सरल शब्दों में, आप byकीवर्ड को इसके द्वारा दिए गए अनुसार समझ सकते हैं ।

संपत्ति उपभोक्ता के दृष्टिकोण से, valकुछ ऐसा है जिसके पास गेटटर (मिलता है) है और varवह चीज है जिसके पास गेटटर और सेटर है (प्राप्त करें, सेट करें)। प्रत्येक varप्रॉपर्टी के लिए प्राप्त करने और सेट करने के तरीकों का एक डिफ़ॉल्ट प्रदाता है जिसे हमें स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता नहीं है।

लेकिन, byकीवर्ड का उपयोग करते समय , आप यह कह रहे हैं कि यह गेटटर / गेट्टर और सेटर कहीं और प्रदान किया जाता है (यानी इसे प्रत्यायोजित किया गया है)। यह उस फ़ंक्शन द्वारा प्रदान किया जाता है जो बाद में आता है by

इसलिए, इस बिल्ट-इन गेट और सेट विधियों का उपयोग करने के बजाय, आप उस नौकरी को कुछ स्पष्ट कार्य के लिए सौंप रहे हैं।

एक बहुत ही सामान्य उदाहरण by lazyआलसी लोडिंग गुणों के लिए है। इसके अलावा, यदि आप कोइन की तरह निर्भरता इंजेक्शन लाइब्रेरी का उपयोग कर रहे हैं, तो आपको इस तरह परिभाषित कई गुण दिखाई देंगे:

var myRepository: MyRepository by inject()  //inject is a function from Koin

कक्षा की परिभाषा में, यह उसी सिद्धांत का अनुसरण करता है, यह परिभाषित करता है कि कुछ फ़ंक्शन प्रदान किया गया है, लेकिन यह किसी भी तरीके / गुणों का उल्लेख कर सकता है, न कि केवल प्राप्त करने और सेट करने के लिए।

class MyClass: SomeInterface by SomeImplementation, SomeOtherInterface

यह कोड कह रहा है: 'मैं क्लास माईक्लास हूं और मैं इंटरफ़ेस SomeInterface के फ़ंक्शंस प्रदान करता हूं जो SomeIm कार्यान्वयन द्वारा प्रदान किए जाते हैं। मैं खुद से SomeOtherInterface लागू करूंगा (यह निहित है, इसलिए byवहां नहीं )। '


23

यहां छवि विवरण दर्ज करें

वाक्य रचना है:

val/var <property name>: <Type> by <expression>. 

इसके बाद की अभिव्यक्ति प्रतिनिधि है

अगर हम संपत्ति के मूल्य तक पहुँचने का प्रयास पी , दूसरे शब्दों में, अगर हम कहते हैं () प्राप्त संपत्ति की विधि पी , getValue () की विधि प्रतिनिधि उदाहरण शुरू हो जाती है।

हम संपत्ति का मूल्य निर्धारित करने के लिए प्रयास करते हैं तो पी , दूसरे शब्दों में, अगर हम कहते हैं () की स्थापना की संपत्ति की विधि पी , setValue () की विधि प्रतिनिधि उदाहरण शुरू हो जाती है।


7

संपत्ति के लिए प्रतिनिधिमंडल:

import kotlin.reflect.KProperty

class Delegate {
    // for get() method, ref - a reference to the object from 
    // which property is read. prop - property
    operator fun getValue(ref: Any?, prop: KProperty<*>) = "textA"
    // for set() method, 'v' stores the assigned value
    operator fun setValue(ref: Any?, prop: KProperty<*>, v: String) {
        println("value = $v")
    }
}

object SampleBy {
    var s: String by Delegate() // delegation for property
    @JvmStatic fun main(args: Array<String>) {
        println(s)
        s = "textB"
    }
}

परिणाम:

textA
value = textB

वर्ग के लिए प्रतिनिधिमंडल:

interface BaseInterface {
    val value: String
    fun f()
}

class ClassA: BaseInterface {
    override val value = "property from ClassA"
    override fun f() { println("fun from ClassA") }
}

// The ClassB can implement the BaseInterface by delegating all public 
// members from the ClassA.
class ClassB(classA: BaseInterface): BaseInterface by classA {}

object SampleBy {
    @JvmStatic fun main(args: Array<String>) {
        val classB = ClassB(ClassA())
        println(classB.value)
        classB.f()
    }
}

परिणाम:

property from ClassA
fun from ClassA

मापदंडों के लिए प्रतिनिधिमंडल:

// for val properties Map is used; for var MutableMap is used
class User(mapA: Map<String, Any?>, mapB: MutableMap<String, Any?>) {
    val name: String by mapA
    val age: Int by mapA
    var address: String by mapB
    var id: Long by mapB
}

object SampleBy {
    @JvmStatic fun main(args: Array<String>) {
        val user = User(mapOf("name" to "John", "age" to 30),
        mutableMapOf("address" to "city, street", "id" to 5000L))

        println("name: ${user.name}; age: ${user.age}; " +
        "address: ${user.address}; id: ${user.id}")
    }
}

परिणाम:

name: John; age: 30; address: city, street; id: 5000
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.