स्थैतिक तरीके केवल स्थैतिक डेटा का उपयोग क्यों कर सकते हैं?


38

मुझे समझ में नहीं आता है कि एक स्थैतिक विधि गैर-स्थैतिक डेटा का उपयोग क्यों नहीं कर सकती है। क्या कोई बता सकता है कि समस्याएं क्या हैं और हम ऐसा क्यों नहीं कर सकते?


11
क्योंकि स्थैतिक विधियों के दृष्टिकोण से केवल स्थैतिक डेटा मौजूद है।
मौविसील

4
अपने शोध को साझा करना हर किसी की मदद करता है। हमें बताएं कि आपने क्या प्रयास किया है और यह आपकी आवश्यकताओं को पूरा क्यों नहीं करता है। यह दर्शाता है कि आपने खुद को मदद करने का प्रयास करने के लिए समय लिया है, यह हमें स्पष्ट उत्तरों को दोहराने से बचाता है, और सबसे अधिक यह आपको अधिक विशिष्ट और प्रासंगिक उत्तर प्राप्त करने में मदद करता है। यह भी देखें कैसे पूछें
gnat

19
@gnat इस मामले में ओपी एक डिजाइन निर्णय के पीछे के कारण को समझने की कोशिश कर रहा है। आप उनसे इस मामले में क्या उम्मीद करते हैं?
गीक

2
@ गीक - स्टैटिक मेथड्स का अस्तित्व, स्टैटिक डेटा लैंग्वेज डिजाइन इश्यू है। मानक अर्थों को मानते हुए, यह तथ्य कि स्थैतिक विधियाँ आवृत्ति डेटा तक नहीं पहुँच सकती हैं। सीमा को परिभाषाओं द्वारा निहित किया गया है और जो संभव है और समझ में आता है, कुछ भाषा डिजाइनरों द्वारा नहीं।
183 पर स्टीव 314

6
व्याख्या करने के लिए Gertrude Stein: "कोई है इस वहाँ।"
हिप्पो-डांसर

जवाबों:


73

अधिकांश OO भाषाओं में, जब आप किसी वर्ग के अंदर एक विधि को परिभाषित करते हैं, तो यह एक Instance Method बन जाता है । जब आप उस वर्ग का एक नया उदाहरण बनाते हैं , तो newकीवर्ड के माध्यम से , आप डेटा के एक नए सेट को केवल उस उदाहरण के लिए विशिष्ट बनाते हैं। उस उदाहरण से संबंधित विधियाँ आपके द्वारा निर्धारित डेटा के साथ काम कर सकती हैं।

इसके विपरीत स्टैटिक मेथड , व्यक्तिगत वर्ग के उदाहरणों से अनभिज्ञ हैं। स्थिर विधि C या C ++ में एक नि: शुल्क फ़ंक्शन के समान है। यह वर्ग के एक विशिष्ट तात्कालिकता से बंधा नहीं है। यही कारण है कि वे उदाहरण के मूल्यों का उपयोग नहीं कर सकते हैं। से मूल्य लेने के लिए कोई उदाहरण नहीं है!

स्थैतिक डेटा एक स्थिर विधि के समान है। ऐसा मान घोषित staticकिया गया है जिसका कोई संबद्ध उदाहरण नहीं है। यह हर उदाहरण के लिए मौजूद है , और केवल एक ही स्थान पर स्मृति में घोषित किया गया है। यदि यह कभी बदल जाता है, तो यह उस वर्ग के हर उदाहरण के लिए बदल जाएगा।

एक स्टेटिक विधि स्टैटिक डेटा तक पहुंच सकती है क्योंकि वे दोनों एक वर्ग के विशिष्ट उदाहरणों से स्वतंत्र रूप से मौजूद हैं।

यह देखने के लिए मदद कर सकता है कि आप एक उदाहरण विधि की तुलना में एक स्थिर पद्धति को कैसे लागू करते हैं। मान लें कि हमारे पास निम्न वर्ग (जावा-जैसे छद्म कोड का उपयोग करके) है:

class Foo {
    // This static value belongs to the class Foo
    public static final string name = "Foo";

    // This non-static value will be unique for every instance
    private int value;

    public Foo(int value) {
         this.value = value;
    }

    public void sayValue() {
        println("Instance Value: " + value);
    }

    public static void sayName() {
        println("Static Value: " + name);
    }
}

Foo foo1 = new Foo(10);
Foo foo2 = new Foo(20);

foo1.sayValue(); // Prints "Instance Value: 10" - called on foo1
foo2.sayValue(); // Prints "Instance Value: 20" - called on foo2

Foo.sayName(); // Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)

अद्यतन करें

के रूप में से आओ टिप्पणी में बताते हैं, एक स्थिर विधि है गैर स्थैतिक डेटा के साथ काम करने में सक्षम है, लेकिन यह स्पष्ट रूप से भेजे जाने चाहिए। मान लेते हैं कि Fooकक्षा के पास एक और तरीका था:

public static Foo Add(Foo foo1, Foo foo2) {
    return new Foo(foo1.value + foo2.value);
}

Addअभी भी स्थिर है, और valueइसका अपना कोई उदाहरण नहीं है , लेकिन फू के वर्ग का सदस्य होने के कारण यह valueउत्तीर्ण foo1और foo2उदाहरण के निजी क्षेत्रों तक पहुंच सकता है । इस मामले में, हम इसका उपयोग नए पास Foo किए गए मानों के जोड़े गए मानों के साथ एक नया वापस करने के लिए कर रहे हैं।

Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30

30
"वहाँ से कोई मान लेने के लिए कोई उदाहरण नहीं है" पर विस्तार हो रहा है - भले ही उदाहरण हैं, स्थैतिक विधि से यह नहीं पता चल सकता है कि किस मूल्य से मूल्य लेना है।
183 पर स्टीव 314

9
यह उन भाषाओं में व्याख्या करने के लिए बहुत कम जटिल है जो हर चीज को डिफ़ॉल्ट रूप से किसी वस्तु का हिस्सा होने के लिए मजबूर नहीं करते हैं।
मेसन व्हीलर

3
@ मेसन सच्चे शब्द। जावा जैसी भाषाएं एक गलत धारणा को लागू करती हैं कि एक फ़ंक्शन एक ऐसी चीज है जो जरूरी एक वर्ग से संबंधित है।
KChaloux

5
यह एक अच्छा जवाब है, लेकिन यह अभी भी पूरी सच्चाई बताने में विफल है: स्थैतिक तरीके गैर-स्थैतिक डेटा तक पहुंच सकते हैं । उनके पास केवल निहित वस्तु या this-प्राप्ति उपलब्ध नहीं है। मुझे लगता है कि यह समझना महत्वपूर्ण है।
आते हैं

2
@COMEFROM आपका मतलब स्पष्ट पासिंग से है? मैं इसका एक नोट बना सकता हूं, अगर मैं आपको सही तरीके से समझ रहा हूं। मैंने माना कि यह निहित है कि एक स्थैतिक विधि स्पष्ट रूप से पारित गैर-स्थैतिक डेटा तक पहुंच सकती है, यह देखते हुए कि कोई भी फ़ंक्शन डेटा पर काम कर सकता है।
KChaloux

22

इसे एक काल्पनिक नमूने के साथ समझाते हैं।

एक साधारण वर्ग की कल्पना करें:

class User
{
User(string n) { name = n; };
string name;
}

अब हम इस वर्ग के 2 उदाहरण बनाते हैं:

User Bones = new User("Bones");
User Jim = new User("Jim");

अब, सोचो - क्या होगा यदि हम उपयोगकर्ता के लिए एक नई स्थैतिक विधि जोड़ते हैं, जैसे:

static string GetName();

और आप इसे कहते हैं:

string x = User::GetName()

x में क्या होगा? "जिम", "हड्डियों", या कुछ और?

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


2

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


2

यह फ़ील्ड डेटा का उपयोग कर सकता है; निम्नलिखित जावा कोड पर विचार करें:

class MyBean {
    private String myString;

    static void myStaticMethod() {
        myString = "tada";/*not allowed; if this was possible how would 
                           be different from a field without static?*/

        MyBean myBean = new MyBean();//allowed if associated with an instance
        myBean.myString = "tada";
    }
}

हालांकि यह गैर-स्थैतिक डेटा का उपयोग करके तकनीकी रूप से एक स्थिर तरीका हो सकता है, यह बिंदु को याद करता है। बेशक आप एक नया उदाहरण बना सकते हैं और इसे एक्सेस कर सकते हैं। लेकिन यह कुछ भी नहीं है कि staticनेस के साथ क्या करना है ।
बोबसन

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

@ बोबसन आपको कोड और टिप्पणियों को भी पढ़ना चाहिए।
m3th0dman

@BenHocking "हाँ" यहां तक ​​कि मुझे लगता है कि यह अच्छी बात है कि "उदाहरण चर हमेशा वस्तु से जुड़ा होता है"
JAVA

2

मुझे लगता है कि यहां मुद्दा एक समझ का है।

एक तकनीकी दृष्टिकोण से किसी वस्तु के भीतर से स्थैतिक विधि उदाहरण क्षेत्रों को देखने में काफी सक्षम होगी। मुझे दृढ़ता से संदेह है कि इस सवाल का कारण क्या है।

मुद्दा यह है कि ऑब्जेक्ट के बाहर से तरीकों को बुलाया जा सकता है। उस बिंदु पर उन्हें प्रदान करने के लिए कोई उदाहरण डेटा नहीं है - और इस प्रकार कोड को हल करने के लिए कंपाइलर के लिए कोई रास्ता नहीं है। चूंकि उदाहरण डेटा की अनुमति देने से विरोधाभास होता है इसलिए हमें उदाहरण डेटा की अनुमति नहीं देनी चाहिए।


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

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

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

1

इसे एक गैर-वस्तु-उन्मुख आयाम में रहने वाले स्थिर तरीकों के रूप में सोचें।

"ऑब्जेक्ट ओरिएंटेड डायमेंशन" में एक वर्ग एगोस (उदाहरणों) को कई गुना कर सकता है, प्रत्येक अहंकार का अपने राज्य के माध्यम से खुद का विवेक होता है।

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


1

मुझे लगता है कि यह समझाने का सबसे आसान तरीका कुछ कोड को देखना है और फिर विचार करना होगा कि हम कोड के उत्पादन के लिए क्या उम्मीद करेंगे।

// Create three new cars.  Cars have a name attribute.  
Car car1 = new Car("Mazda3");
Car car2 = new Car("FordFocus");
Car car3 = new Car("HondaFit");

// Now we would like to print the names of some cars: 
// First off why don't we try this: 

Car.printCarName();

// Expected behaviour: 
// If we think about what we are trying to do here it doesn't
// really make sense.  What instance of car name should this 
// print?  Should it print Mazda3?  FordFoucs?
// What is the expected behaviour?  If we are going to have a
// static call on car call printCarName it should probably do
// something like print all car names or a random car name or
// throw an error.  


//Now lets try this instead: 

Car.printCarName(car1);

// Expected Behaviour: 
// Luckily the expected behaviour is very clear here.  This
// should print Mazda3.  This works as expected.  


// Finally lets try this: 

car1.printMyName();

// Expected Behaviour:
// Same as previous example, however this is the *right* way
// to do it.  

पूर्णता के लिए यहाँ कार वर्ग है:

public class Car{

    public String name;

    public Car(String name){
        this.name = name;
    }

    public static printCarName(){
        print "Not sure what to do here...  Don't know which car you are talking about.";
    }

    public static printCarName(Car c){
        print c.name;
    }

    public /*NOT static*/ printMyName(){
        print this.name;
    }

}

यह पूछे गए प्रश्न का उत्तर कैसे देता है?
gnat

1
@gnat टिप्पणी के साथ अद्यतन स्पष्ट करने के लिए।
साठफुटेरसूड

1

अन्य जवाब बहुत ज्यादा यह सब कहते हैं, हालांकि, कुछ "विस्तार" है जो मैं जोड़ना चाहूंगा।

स्थैतिक विधियाँ (जावा में कहे जाने वाले) उनके पास केवल एक अंतर्निहित वस्तु नहीं है ( thisजिसके माध्यम से सुलभ हो ) जिनके सदस्यों को आप आम तौर पर सीधे नाम से एक्सेस कर सकते हैं।

इसका मतलब यह नहीं है कि वे गैर-स्थैतिक डेटा तक नहीं पहुँच सकते।

class MyClass {
  public static void foo(MyOtherClass object) {
    System.out.println(object.member);
  }
}
class MyOtherClass { public int member = 10; }

मुझे पता है कि यह सिर्फ एक विवरण है, लेकिन जब मैंने इसे पढ़ा तो मुझे आपका सवाल अजीब लगा। "केवल स्थैतिक डेटा का उपयोग कर सकते हैं" बहुत अधिक प्रतिबंधक है।

वैसे, मैंने कोड का परीक्षण नहीं किया, मैंने जो कुछ कह रहा था, उसे उदाहरण के लिए यहाँ लिखा था।

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