स्टैटिक कीवर्ड को समझना


16

मुझे जावा, जावास्क्रिप्ट और पीएचपी के साथ विकसित होने का कुछ अनुभव है।

मैं Microsoft Visual C # 2010 स्टेप बाय स्टेप पढ़ रहा हूं जो मुझे लगता है कि यह आपको C # भाषा से परिचित कराने की एक बहुत अच्छी किताब है।

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

लेकिन स्थैतिक कीवर्ड का वास्तविक उद्देश्य क्या है? मुझे स्थिर चर और विधियों की घोषणा कब करनी चाहिए?


4
C # में स्थिर जावा में स्थिर के समान है। यदि आप इसे जावा में समझते हैं, तो आपको
बजे

जावा मेरी पहली प्रोग्रामिंग लैंग्वेज थी और मुझे यह कॉन्सेप्ट वहां भी समझ में नहीं आया था। मैंने केवल कुछ समय के लिए जावा का इस्तेमाल किया है
Nistor Alexandru

संक्षेप में: "स्थिर" का उपयोग करें जब आपको कोई ऑब्जेक्ट ओरिएंटेशन की आवश्यकता होती है, उदाहरण के लिए, बस कुछ स्टैंड-अलोन तरीके या चर। एक वर्ग को स्थिर घोषित करने का मतलब उन गैर-वस्तु उन्मुख कार्यों और चर को केवल एक सामान्य नाम (स्थान), वर्ग नाम में रखना है।
डॉक्टर ब्राउन

जवाबों:


15

C # में 'स्टेटिक' कीवर्ड क्लास, या क्लास में ही किसी चीज को संदर्भित कर रहा है, जो कि क्लास के सभी उदाहरणों के बीच साझा किया गया है। उदाहरण के लिए, एक फ़ील्ड जिसे स्थिर के रूप में चिह्नित किया गया है, उस वर्ग के सभी उदाहरणों से वर्ग नाम के माध्यम से पहुँचा जा सकता है।

public class SomeObject
{
    //Static Field
    static int Foo = 3;

    //instance field
    private int _Foo2 = 4;

    //instance property
    public int Foo2{get{return _Foo2;}set{_Foo2 = value;}}


    //static factory method
    public static SomeObject CreateSomeObject(int fooValue)
    {
        SomeObject retVal = new SomeObject();
        retVal.Foo2 = fooValue;
        return retVal;
    }

    //Parameterless instance constructor
    public SomeObject()
    {
    }

    public static int Add(int x)
    {
        //Static methods can only deal with local variables, or fields that
        //  are also static in the class.  This one adds x to the static member foo
        return x + Foo;

        //Foo2 is not accessable here!
    }

      //Instance method
    public int AddSomething(int x)
    {
        //Add x to the property value of Foo2
        return x + this.Foo2;

        //Note that Foo *is* accessable here as 'SomeObject.Foo'
    }

}

मैं ईमानदारी से कह सकता हूं कि मैंने एक्स्टेंशन मेथड (एक्सट्रीम ट्यूटोरियल ऑन एक्सटेंशन मेथड्स ) बनाने के अपवाद के साथ स्टैटिक के रूप में चिन्हित क्लास का इस्तेमाल कभी नहीं किया है ।

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

इसके साथ पालन करने के लिए, यहाँ बताया गया है कि स्थैतिक और तात्कालिक तरीकों के बीच अंतर, फ़ील्ड और गुणों को कैसे कहा जाता है।

public static void Main(string[] args)
{
    //This is a static method that starts a thread in an application
    // space.  At this point not everything actually has to be static...

    //Here is an instantiation with a parameterless contruction
    SomeObject obj = new SomeObject();

    //Here is an instantiation using a static factory method
    SomeObject obj2 = SomeObject.CreateSomeObject(3);

    //Getting field value from static field
    // Notice that this references the class name, not an instance
    int fooValue1 = SomeObject.Foo;

    //Getting property value from instance
    //  Note that this references an object instance
    int fooValue2 = obj2.Foo2;

    //Instance method must be called through an object
    obj2.AddSomething(4);  //if default constructor, would return 8

    //Static methods must be called through class name
    SomeObject.Add(4); //Returns 7
}

इसके अलावा, इस पोस्ट को स्टैटिक क्लासेज में गहराई से देखें।


19

यहाँ यहोशू बलोच के समझाने का तरीका है, जो मुझे सबसे अधिक शानदार लगता है जैसे वह कहता है (हाँ मैं एक जोशुआ बलोच प्रशंसक लड़का हूँ :))। यह स्मृति से उद्धृत किया गया है।

कल्पना कीजिए कि एक वर्ग एक घर के लिए ब्लू-प्रिंट के बराबर है। तब कल्पना कीजिए कि एक घर ब्लू-प्रिंट के लिए है जैसा कि कक्षा के लिए है। आपके पास इससे निर्मित एक वर्ग (ब्लू-प्रिंट) और कई उदाहरण (घर) हो सकते हैं।

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

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


या आपके पास एक ऐसा Blueprintवर्ग होगा जो ब्लूप्रिंट की कार्यक्षमता को लागू करता है, जिसमें ब्लूप्रिंट द्वारा व्यक्त किए गए घर के पदचिह्न की गणना करने की क्षमता भी शामिल है। यह खाका उदाहरण तब खिलाया जाता है Builder(बदले में स्वयं एक उदाहरण की संभावना है), जो बदले में Buildingएक खाका के आधार पर संभावित मनमाने ढंग से संख्याओं के निर्माण और उत्पादन के लिए आवश्यक है ।
एक CVn

12

इसे इस तरह से देखने से मुझे मदद मिलती है:

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

स्थैतिक कीवर्ड का उपयोग कब करें:

  • किसी भी विधि को स्थानीय संपत्तियों तक पहुंच की आवश्यकता नहीं है और शायद इसे स्थिर घोषित किया जाना चाहिए।
  • हेल्पर कक्षाएं जिनके पास कोई भी राज्य नहीं है (जो वैसे भी दुर्लभ होना चाहिए) और जिसका कभी भी मजाक नहीं किया जाएगा उन्हें स्थिर घोषित किया जा सकता है। चाहे उन्हें कोई और मामला हो; इस कार्यक्षमता का संयम से उपयोग करें।
  • ऐसे गुण और क्षेत्र जिन्हें किसी वर्ग के सभी उदाहरणों तक पहुँचा जाना चाहिए उन्हें स्थिर घोषित किया जाना चाहिए। लेकिन इसका इस्तेमाल तभी करें जब कोई दूसरा विकल्प न हो।

+1, एक अच्छे सारांश के लिए, मुझे नहीं पता था कि हर प्रकार का 1 स्थिर उदाहरण है और मुझे आपको सच बताने में अजीब लगता है।
NoChance

2
@EmmadKareem यह सिर्फ एक मानसिक मॉडल पीडीआर का उपयोग करता है, क्योंकि "Looking at it this way helps"उसे। आपको यह अजीब लगता है क्योंकि यह बिल्कुल सच नहीं है, लेकिन आप इसे इस तरह से सोच सकते हैं यदि आप चाहते हैं। क्या आप बोह्र मॉडल को जानते हैं? यह नियमों और विचारों का एक सेट प्रस्तुत करता है कि कैसे परमाणु और इलेक्ट्रॉन एक दूसरे के साथ बातचीत करते हैं। मॉडल तुम क्या करते के आधार पर काम करता है, लेकिन यह वास्तविकता नहीं है।
प्रेत ०

@ phant0m, स्पष्टीकरण के लिए धन्यवाद, मैं इस धारणा के तहत था कि यह वास्तविक नहीं एक मॉडल था और मैं इस वजह से आश्चर्यचकित था।
NoChance

वास्तव में, कभी-कभी ऐसे कारण होते हैं, जिनके staticमाध्यम से आप स्थानीय गुणों का उपयोग नहीं करना चाहते हैं। चीजें बनाने staticसे ग्राहकों को युग्मन मिल सकता है क्योंकि उन्हें सीधे कक्षा को संबोधित करना होगा। उदाहरण के लिए, यह इकाई परीक्षण w / मॉकिंग को और अधिक कठिन बना सकता है।
एलन

@Allan: यकीनन, यदि आप किसी ऐसे वर्ग पर एक सार्वजनिक पद्धति को कॉल कर रहे हैं जो उस वर्ग की आवृत्ति की स्थिति को प्रभावित नहीं करता है, तो वह क्लाइंट डेवलपर को स्पष्ट करने के लिए स्थिर होना चाहिए। अगर वह तरीका इतना अधिक है कि उसे मजाक करने की ज़रूरत है, तो यह एक अलग समस्या है जिसे कई तरीकों से हल किया जा सकता है।
पीडीआर

4

सबसे सरल स्पष्टीकरण --- स्टेटिक => प्रति वातावरण में केवल एक प्रति मौजूद होगी।

इसलिए वीएम या सीएलआर के भीतर केवल एक स्थिर वर्ग की एक ही प्रति होगी, और इसका संदर्भ देने वाले किसी भी अन्य वर्ग को अपने तरीकों और डेटा को अन्य सभी वर्गों के साथ साझा करना होगा।

स्टैटिक वैरिएबल के लिए, रन टाइम के माहौल में इस वैरिएबल का केवल एक ही उदाहरण होगा, चाहे वह किसी भी स्टैटिक वेरिएबल की रेफरेंस क्यों न हो, लेकिन जब वे स्टैटिक वैरिएबल के एक ही टुकड़े को रेफर करेंगे।


2

स्टैटिक सदस्य क्लास से जुड़े होते हैं, उस क्लास के किसी भी उदाहरण के साथ नहीं।

चूंकि हम .Net के बारे में बात कर रहे हैं, स्ट्रिंग वर्ग पर विचार करें , विशेष रूप से स्प्लिट और जॉइन विधियों में।

विभाजन एक उदाहरण विधि है। एक स्ट्रिंग चर बनाएं, इसे एक मूल्य दें और आप उस चर / मूल्य पर स्प्लिट () कॉल कर सकते हैं और "बिट्स" की एक सरणी वापस पा सकते हैं:

String s1 = "abc,def,ghi" ; 
String[] array2 = s1.Split( ',' ) ; 

इसलिए, उदाहरण के तरीकों के लिए, दिए गए वर्ग के उदाहरण के भीतर आयोजित मूल्य मायने रखता है

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

String[] array3 = { ... } 
s1 = String.Join( array3, "," ) ; 

उदाहरण के लिए एक और विकल्प हो सकता है कि ज्वाइन विधि, जहाँ स्ट्रिंग [वर्ग उदाहरण] के भीतर आयोजित मूल्य को हम शामिल होने वाले सीमांकक के रूप में उपयोग करते हैं, कुछ इस प्रकार है:

// Maybe one day ... 
String s4 = "," ; 
s1 = s4.Join( array3 ) ; 

2

staticNewbies समझ के लिए कीवर्ड एक छोटे से कठिन हो सकता है। इसका प्राथमिक उद्देश्य वर्ग सदस्य की पहचान करना है क्योंकि वह कक्षा के किसी एक उदाहरण से संबंधित नहीं है, बल्कि केवल कक्षा के बजाय।

बहुत अधिक विस्तार में जाने के बिना, सी # (और जावा) वस्तु-उन्मुख आदर्श को सख्ती से लागू करता है कि सभी कोड और डेटा एक वस्तु से संबंधित होने चाहिए, और इसलिए यह गुंजाइश, दृश्यता और जीवनकाल में सीमित है। यह आमतौर पर सबसे अच्छा अभ्यास है जहाँ किसी वास्तविक दुनिया की चीज़ का प्रतिनिधित्व करने वाली वस्तु का मूल सिद्धांत लागू होता है। हालाँकि, यह हमेशा नहीं होता है; कभी-कभी आपको जिस चीज़ की आवश्यकता होती है वह एक फ़ंक्शन या वैरिएबल है जिसे आप कोड में कहीं से भी प्राप्त कर सकते हैं , इसके लिए आपको किसी ऑब्जेक्ट के संदर्भ में इसे पास करने की आवश्यकता नहीं है, और इस बात की गारंटी के साथ कि जिस डेटा को आप देख रहे हैं या बदल रहे हैं, वह वास्तव में हर कोई है और किसी वस्तु के एक अलग उदाहरण से संबंधित है, न कि उसके साथ काम कर रहा है।

इस तरह का व्यवहार "वैश्विक" फ़ंक्शन या चर के रूप में C और C ++ में उपलब्ध था, जो किसी ऑब्जेक्ट में एनकैप्सुलेटेड नहीं था। तो, एक समझौता के रूप में, C # और Java "स्टैटिक स्कोप" का समर्थन करता है, कोई अभिभावक वस्तु और सीमित-स्कोप उदाहरण सदस्यों के साथ सही मायने में वैश्विक कोड के बीच का आधा बिंदु।

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

public class Foo
{
   public int MyInt {get;set;} //this is an "instance member"
   public static int MyStaticInt {get;set;} //this is a "static member"
}

...

var myFoo = new Foo();
myFoo.MyInt = 5; //valid
myFoo.MyStaticInt = 5; //invalid; MyStaticInt doesn't belong to any one Foo

Foo.MyInt = 5; //invalid; MyInt only has meaning in the context of an instance
Foo.MyStaticInt = 2; //valid

यह स्थिर सदस्यों को किसी भी कोड को दिखाता है, जिसे इस प्रकार का ज्ञान होता है, चाहे वे इसके किसी एक उदाहरण के बारे में जानते हों या नहीं।

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

संपूर्ण कक्षाओं को स्थैतिक भी चिह्नित किया जा सकता है; ऐसा करने से, आप संकलक को बताते हैं कि कक्षा की घोषणा में केवल स्थैतिक सदस्य शामिल होंगे, और इस तरह इसे तत्काल नहीं किया जा सकता है। यह सुनिश्चित करने का एक आसान तरीका है कि एक, और केवल एक, स्मृति में किसी वस्तु की प्रतिलिपि; कक्षा और उसमें सब कुछ स्थिर करें। हालांकि, यह बहुत दुर्लभ है कि यह इस तरह की जरूरत का सबसे अच्छा समाधान है। ऐसी स्थिति में जहां डेटा के सेट की एक प्रतिलिपि की आवश्यकता होती है, "सिंगलटन" को आमतौर पर इसके बजाय वकालत की जाती है; यह एक गैर-स्थिर वर्ग है, जो स्वयं के एकल उदाहरण तक पहुँच प्रदान करने के लिए एक स्थिर अभिगमकर्ता और एक गैर-सार्वजनिक निर्माणकर्ता का उपयोग करता है। सैद्धांतिक रूप से, एक सिंगलटन पूरी तरह से स्थिर वर्ग के समान लाभ प्रदान करता है, लेकिन उदाहरण-आधारित, ऑब्जेक्ट-ओरिएंटेड तरीके से क्लास का उपयोग करने की अतिरिक्त क्षमता के साथ।

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