स्थैतिक तरीके जावा में विरासत में मिले हैं?


142

मैं खालिद मुगल द्वारा जावा प्रोग्रामर एससीजेपी सर्टिफिकेट के लिए ए प्रोग्रामर गाइड पढ़ रहा था ।

इनहेरिटेंस अध्याय में, यह बताते हैं कि

सदस्यों की विरासत उनके घोषित सुगमता से निकटता से जुड़ी हुई है। यदि एक सुपरक्लास सदस्य उपवर्ग में अपने सरल नाम से पहुंचता है (सुपर जैसे किसी भी अतिरिक्त सिंटैक्स के उपयोग के बिना), तो उस सदस्य को विरासत में माना जाता है

यह भी उल्लेख करता है कि स्थिर तरीके विरासत में नहीं मिले हैं। लेकिन नीचे दिया गया कोड एकदम ठीक है:

class A
{
    public static void display()
    {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A
{
    public void show()
    {
        // This works - accessing display() by its simple name -
        // meaning it is inherited according to the book.
        display();
    }
}

मैं display()कक्षा में सीधे उपयोग कैसे कर सकता हूं B? और B.display()भी , काम भी करता है।

क्या पुस्तक की व्याख्या केवल उदाहरण के तरीकों पर लागू होती है?


stackoverflow.com/questions/4716040/… की रोचक जानकारी है।
Mat

यह मेरी प्रति, 1 संस्करण में ऐसा नहीं है। कृपया एक वास्तविक उद्धरण प्रदान करें।
लोरेन के मार्किस

जवाबों:


179

सभी तरीके जो सुलभ हैं वे उपवर्गों द्वारा विरासत में मिले हैं।

सन जावा ट्यूटोरियल से :

एक उपवर्ग अपने माता-पिता के सभी सार्वजनिक और संरक्षित सदस्यों को विरासत में देता है, भले ही उपवर्ग में कोई भी पैकेज हो। यदि उपवर्ग अपने माता-पिता के समान पैकेज में है, तो यह अभिभावक के पैकेज-निजी सदस्यों को भी विरासत में मिलता है। आप विरासत में मिले सदस्यों का उपयोग कर सकते हैं, उन्हें बदल सकते हैं, उन्हें छिपा सकते हैं, या नए सदस्यों के साथ पूरक कर सकते हैं

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

ओवरराइड करने और छिपाने के बीच के अंतर पर पेज से ।

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


विरासत में मिला है, तो क्या हम उस सदस्य को उपवर्ग में ओवरराइड कर सकते हैं?
एलगोरिदमिस्ट

खैर, यह विरासत का हिस्सा है, लेकिन यह सब नहीं है। मैं कहूंगा कि विरासत के अन्य प्रमुख भाग कोड का पुन: उपयोग और बहुरूपता है।
यिनक्रैश २४'१२

क्या पुनर्परिभाषित करने के कुछ नियम भी हैं जैसे ओवरराइडिंग के कुछ नियम हैं?
सुरेंद्र ठाकरान

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

1
आपका अंतिम पैराग्राफ पूरी तरह से कम आंका गया है !!! "ओवरराइड विधि का संस्करण, जो उपविभाजित हो जाता है, उपवर्ग में एक है" यह सच नहीं है: मान लीजिए: ओवरराइड विधि का संस्करण जो केवल आह्वान किया जाता है, केवल JVM द्वारा रनटाइम में निर्धारित किया जाता है कि किस वस्तु से संबंधित है कॉल :)
मौनिम

14

अगर वास्तव में किताब यही कहती है, तो यह गलत है। [१]

जावा भाषा विशिष्टता # 8.4.8 कहता है:

8.4.8 वंशानुक्रम, ओवरराइडिंग और छिपाना

एक वर्ग C को अपने सीधे सुपरक्लास से सभी ठोस तरीके मिलते हैं जो सुपरक्लास के सभी स्थिर और उदाहरण हैं, जिसके लिए निम्नलिखित सभी सत्य हैं:

  • m, C के प्रत्यक्ष सुपरक्लास का सदस्य है।

  • m सार्वजनिक है, संरक्षित है, या C के समान पैकेज में पैकेज एक्सेस के साथ घोषित किया गया है।

  • C में घोषित किसी भी विधि में एक हस्ताक्षर नहीं है जो m के हस्ताक्षर का एक अंश (.28.4.2) है।

[१] यह नहीं कहता कि मेरी प्रति, १ संस्करण, २००० में।


13

आप निम्नलिखित कोड में अंतर का अनुभव कर सकते हैं, जो आपके कोड पर थोड़ा संशोधन है।

class A {
    public static void display() {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A {
    public void show() {
        display();
    }

    public static void display() {
        System.out.println("Inside static method of this class");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // prints: Inside static method of this class
        b.display();

        A a = new B();
        // prints: Inside static method of superclass
        a.display();
    }
}

यह स्थैतिक विधियों के कारण वर्ग विधियां हैं।

A.display () और B.display () उनकी संबंधित कक्षाओं की विधि को कहेंगे।


1
उदाहरण के लिए एक स्थैतिक विधि को लागू करना जैसे आप जावा में काम नहीं करेंगे।
लुकास सी। फिजो

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

2
@ LucasC.Feijo वास्तव में मैं यह काम करता है। कम से कम मेरी आईडीई (ग्रहण) में। मुझे सिर्फ एक चेतावनी मिलती है। यह भले ही अच्छी शैली न हो ... लेकिन यह एक अलग कहानी है।
डिंगलपदुम

2
@ LucasC.Feijo एक उदाहरण पर एक स्थिर विधि की सिफारिश नहीं है। लेकिन यह क्लास नाम पर एक स्थिर विधि को कॉल करने के समान है।
ज़ियांग झांग

5

B.display () काम करता है क्योंकि स्थैतिक घोषणा विधि / सदस्य को वर्ग से संबंधित बनाती है, न कि किसी विशेष वर्ग उदाहरण (उर्फ ऑब्जेक्ट) के लिए। आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं ।

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


3

जावा में स्टेटिक तरीके विरासत में मिले हैं, लेकिन इसे ओवरराइड नहीं किया जा सकता है। यदि आप एक उपवर्ग में समान विधि घोषित करते हैं, तो आप इसे ओवरराइड करने के बजाय सुपरक्लास विधि छिपाते हैं। स्थैतिक विधियाँ बहुरूपी नहीं हैं। संकलन के समय, स्टैटिक विधि सांख्यिकीय रूप से जुड़ी होगी।

उदाहरण:

public class Writer {
    public static void write() {
        System.out.println("Writing");
    }
}

public class Author extends Writer {
    public static void write() {
        System.out.println("Writing book");
    }
}

public class Programmer extends Writer {

    public static void write() {
        System.out.println("Writing code");
    }

    public static void main(String[] args) {
        Writer w = new Programmer();
        w.write();

        Writer secondWriter = new Author();
        secondWriter.write();

        Writer thirdWriter = null;
        thirdWriter.write();

        Author firstAuthor = new Author();
        firstAuthor.write();
    }
}

आपको निम्नलिखित मिलेगा:

Writing
Writing
Writing
Writing book

2

स्थैतिक तरीके जावा में विरासत में मिले हैं, लेकिन वे बहुरूपता में भाग नहीं लेते हैं। यदि हम स्थैतिक तरीकों को ओवरराइड करने का प्रयास करते हैं तो वे उन्हें ओवरराइड करने के बजाय केवल सुपरक्लास स्थिर तरीकों को छिपाएंगे।


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

2

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


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

0

स्थैतिक विधि उपवर्ग में विरासत में मिली है लेकिन यह बहुरूपता नहीं है। जब आप स्थैतिक विधि के कार्यान्वयन को लिखते हैं, तो माता-पिता की कक्षा विधि छिपी हुई है, ओवरराइड नहीं है। सोचें, अगर यह विरासत में नहीं मिली है तो आप बिना पहुंच के कैसे सक्षम हो सकते हैं classname.staticMethodname();?


0

सभी सार्वजनिक और संरक्षित सदस्यों को किसी भी वर्ग से विरासत में लिया जा सकता है, जबकि डिफ़ॉल्ट या पैकेज के सदस्यों को भी सुपरक्लास के समान पैकेज के भीतर वर्ग से विरासत में मिला जा सकता है। यह निर्भर नहीं करता है कि यह स्थिर या गैर स्थिर सदस्य है या नहीं।

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


0

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

public class A {

    public static void display(){
        System.out.println("in static method of A");
    }
}

public class B extends A {

    void show(){
        display();
    }

     public static void display(){
        System.out.println("in static method of B");
    }

}
public class Test {

    public static void main(String[] args){
        B obj =new B();
        obj.show();

        A a_obj=new B();
        a_obj.display();


    }


}

पहले मामले में, ओ / पी "बी के स्थिर विधि में" # सफल ओवरराइड है। 2 के मामले में, ओ / पी "स्थिर विधि में ए" # स्टेटिक विधि है - बहुरूपता पर विचार नहीं करेगा


-1

हम उपवर्ग में एक ही हस्ताक्षर के साथ स्थैतिक तरीकों की घोषणा कर सकते हैं, लेकिन इसे ओवरराइडिंग नहीं माना जाता है क्योंकि कोई रन-टाइम पॉलिमोर्फ़िज्म नहीं होगा। लेकिन क्योंकि क्लास के सभी स्टैटिक सदस्यों को क्लास लोडिंग के समय लोड किया जाता है, इसलिए इसे संकलित करने का निर्णय लें समय (रन टाइम में ओवरराइड करना) इसलिए उत्तर 'नहीं' है।


2
मुझे नहीं पता कि लोग हमेशा डाउन-वोट क्यों करते हैं और डाउन-वोटिंग का कारण नहीं देते हैं।
surajs1n

यह उत्तर ओवरराइड करने के बारे में है। सवाल विरासत के बारे में है।
लोर्ने

-1

कई लोगों ने उनके जवाब को शब्दों में बयां किया है। यह कोडों में एक विस्तारित व्याख्या है:

public class A {
    public static void test() {
        System.out.println("A");
    }
    public static void test2() {
        System.out.println("Test");
    }
}

public class B extends A {
    public static void test() {
        System.out.println("B");
    }
}

// Called statically
A.test();
B.test();
System.out.println();

// Called statically, testing static inheritance
A.test2();
B.test2();
System.out.println();

// Called via instance object
A a = new A();
B b = new B();
a.test();
b.test();
System.out.println();

// Testing inheritance via instance call
a.test2();
b.test2();
System.out.println();

// Testing whether calling static method via instance object is dependent on compile or runtime type
((A) b).hi();
System.out.println();

// Testing whether null instance works
A nullObj = null;
nullObj.hi();

परिणाम:

A
B

Test
Test

A
B

Test
Test

A

A

इसलिए, यह निष्कर्ष है:

  1. जब हम स्थैतिक को स्थैतिक तरीके से बुलाते हैं। यह उस वर्ग में परिभाषित स्थैतिक के लिए दिखेगा, या वंशानुक्रम श्रृंखला में उसके निकटतम वर्ग। यह साबित करता है कि स्थिर तरीके विरासत में मिले हैं।
  2. जब स्थिर विधि को उदाहरण से पुकारा जाता है, तो यह संकलन-समय प्रकार में परिभाषित स्थैतिक विधि को बुलाता है।
  3. एक nullउदाहरण से स्थैतिक विधि को बुलाया जा सकता है । मेरा अनुमान है कि कंपाइलर संकलन के दौरान वर्ग को खोजने के लिए चर प्रकार का उपयोग करेगा, और उस अनुवाद को उपयुक्त स्थिर विधि कॉल में करेगा।

1
मात्र कोड एक स्पष्टीकरण नहीं है, यह एक प्रदर्शन है। इस प्रश्न का उत्तर मानक संदर्भों का हवाला देना चाहिए, न कि कुछ अस्थिर कार्यान्वयन के व्यवहार का प्रदर्शन करना चाहिए।
लोर्ने

-2

स्थैतिक सदस्य सार्वभौमिक सदस्य होते हैं। इन्हें कहीं से भी एक्सेस किया जा सकता है।


4
शाब्दिक रूप से कहीं भी ले जाया जा सकता है , यह गलत है: स्थिर! = गुंजाइश। आप स्पष्ट करना चाह सकते हैं :-)
kleopatra

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

@ ट्राइंको उत्तर उन तरीकों के मामले में गलत है जो निजी हैं, या पैकेज के बाहर से पैकेज-संरक्षित एक्सेस है।
लोरेन

@kleopatra - ऑफ टॉपिक। जावा स्विंग? क्या लोग वास्तव में इन दिनों का उपयोग करते हैं?
मास्टरजेओ 2

@ पवन कक्षा के बाहर से निजी स्टेटिक कॉल करने का प्रयास करते हैं। यह काम नहीं करेगा।
राकेश यादव

-2

स्थैतिक सदस्यों को उपवर्ग में विरासत में नहीं दिया जाएगा क्योंकि विरासत केवल गैर-स्थैतिक सदस्यों के लिए है .. और स्थिर सदस्यों को क्लास लोडर द्वारा स्थिर पूल के अंदर लोड किया जाएगा। वंशानुक्रम केवल उन सदस्यों के लिए होता है जो वस्तु के अंदर लोड होते हैं


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