ग्रोवी: "डीईएफ़ =" में "डीफ़" का उद्देश्य क्या है?


180

निम्नलिखित कोड में ( ग्रूवी सेमेंटिक्स मैनुअल पेज से लिया गया ), कीवर्ड के साथ असाइनमेंट का उपसर्ग क्यों def?

def x = 0
def y = 5

while ( y-- > 0 ) {
    println "" + x + " " + y
    x++
}

assert x == 5

defकीवर्ड हटाया जा सकता है, और यह टुकड़ा एक ही परिणाम का उत्पादन होगा। तो कीवर्ड का प्रभाव क्या है def?

जवाबों:


278

यह बुनियादी लिपियों के लिए वाक्य रचना चीनी है। "डिफ" कीवर्ड को स्वीकार करते हुए वर्तमान स्क्रिप्ट के लिए बाइंडिंग में वैरिएबल डालता है और ग्रूवी इसे (ज्यादातर) विश्व स्तर पर स्कोपेड वैरिएबल की तरह मानता है:

x = 1
assert x == 1
assert this.binding.getVariable("x") == 1

इसके बजाय डिफ ​​कीवर्ड का उपयोग करने से स्क्रिप्ट बाइंडिंग में वैरिएबल नहीं डालती है:

def y = 2

assert y == 2

try {
    this.binding.getVariable("y") 
} catch (groovy.lang.MissingPropertyException e) {
    println "error caught"
} 

प्रिंट: "त्रुटि पकड़ी गई"

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

यदि आप अपनी स्क्रिप्ट में एक विधि को परिभाषित करते हैं, तो इसका उपयोग उन चर तक नहीं होगा जो मुख्य स्क्रिप्ट के शरीर में "डिफ" के साथ बनाए गए हैं क्योंकि वे दायरे में नहीं हैं:

 x = 1
 def y = 2


public bar() {
    assert x == 1

    try {
        assert y == 2
    } catch (groovy.lang.MissingPropertyException e) {
        println "error caught"
    }
}

bar()

प्रिंट "त्रुटि पकड़ी गई"

"Y" वेरिएबल फ़ंक्शन के अंदर स्कोप नहीं है। "x" स्कोप है क्योंकि ग्रूवी वेरिएबल के लिए वर्तमान स्क्रिप्ट के बाइंडिंग की जांच करेगा। जैसा कि मैंने पहले कहा था, यह बस टाइप करने के लिए त्वरित और गंदी लिपियों को जल्दी (अक्सर एक लाइनर) बनाने के लिए सिंटैक्टिक चीनी है।

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


36

टेड का उत्तर लिपियों के लिए उत्कृष्ट है; कक्षाओं के लिए बेन का जवाब मानक है।

जैसा कि बेन कहते हैं, इसे "ऑब्जेक्ट" के रूप में सोचें - लेकिन यह बहुत ठंडा है कि यह आपको ऑब्जेक्ट विधियों के लिए बाध्य नहीं करता है। आयात के संबंध में इसके निहितार्थ हैं।

उदा। इस स्निपेट में मुझे FileChannel आयात करना होगा

// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*

import java.nio.channels.*

class Foo {
    public void bar() {
        FileChannel channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()

उदाहरण के लिए, यहाँ पर मैं तब तक 'विंग' कर सकता हूँ जब तक कि सब कुछ क्लासपाथ पर है

// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*
class Foo {
    public void bar() {
        def channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()

1
आपको new FileInputStream('Test.groovy').getChannel()आयात करने की अनुमति क्यों दी गई ?
अलेक्जेंडर सुराफेल

3
@ एलेक्ज़ेंडरसुर्फ़ेल "जब तक सब कुछ क्लासपाथ पर है"
हनो नो

30

इस पृष्ठ के अनुसार , defएक प्रकार के नाम के लिए एक प्रतिस्थापन है और बस के लिए एक उपनाम के रूप में सोचा जा सकता है Object(यानी यह दर्शाता है कि आप प्रकार की परवाह नहीं करते हैं)।


12

जहाँ तक इस एकल लिपि का सवाल है, कोई व्यावहारिक अंतर नहीं है।

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

इसलिए, यदि आपके पास दो स्क्रिप्ट हैं और उन्हें एक ही ग्रूवीशेल के साथ निष्पादित किया जाता है, तो दूसरी स्क्रिप्ट उन सभी चरों को प्राप्त करने में सक्षम होगी जो "स्क्रिप्ट" के बिना पहली स्क्रिप्ट में सेट किए गए थे।


8

"डिफ" का कारण ग्रूवी को बताना है कि आप यहां एक चर बनाने का इरादा रखते हैं। यह महत्वपूर्ण है क्योंकि आप कभी भी दुर्घटना से एक चर नहीं बनाना चाहते हैं।

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

यहाँ एक उदाहरण है कि यह खराब क्यों है। यदि आप निम्नलिखित कोड को कॉपी करते हैं और इसे groovysh में पेस्ट करते हैं तो यह (ऐस्सेलर को विफल किए बिना) चलेगा:

bill = 7
bi1l = bill + 3
assert bill == 7

इस तरह की समस्या को खोजने और ठीक करने में बहुत समय लग सकता है - भले ही यह आपके जीवन में केवल एक बार ही हो, फिर भी आपके करियर में स्पष्ट रूप से हजारों बार चर घोषित करने की तुलना में अधिक समय लगेगा। यह भी आँख के सामने स्पष्ट हो जाता है जहाँ यह घोषित किया जा रहा है, आपको अनुमान लगाने की आवश्यकता नहीं है।

महत्वहीन स्क्रिप्ट / कंसोल इनपुट (ग्रूवी कंसोल की तरह) यह कुछ हद तक स्वीकार्य है क्योंकि स्क्रिप्ट का दायरा सीमित है। मुझे लगता है कि केवल यही कारण है कि ग्रूवी आपको स्क्रिप्ट्स में ऐसा करने की अनुमति देता है डीएसएल जिस तरह से रूबी करता है उसका समर्थन करना है (यदि आप मुझसे पूछते हैं तो एक बुरा व्यापार बंद हो जाता है, लेकिन कुछ लोग डीएसएल से प्यार करते हैं)


5

वास्तव में, मुझे नहीं लगता कि यह वही व्यवहार करेगा ...

Groovy में चर को अभी भी घोषणा की आवश्यकता होती है, न कि केवल TYPED घोषणा, क्योंकि दाहिने हाथ की ओर आम तौर पर Groovy के लिए चर को टाइप करने के लिए पर्याप्त जानकारी होती है।

जब मैं एक चर का उपयोग करने की कोशिश करता हूं जिसे मैंने डीफ़ या एक प्रकार के साथ घोषित नहीं किया है, तो मुझे "कोई ऐसी संपत्ति नहीं" मिलती है, क्योंकि यह मानता है कि मैं कोड वाले वर्ग के सदस्य का उपयोग कर रहा हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.