2011-12-29 2 views
7

यह संभवतः एक बुरी चीज है, जैसा कि Can parent and child class in Java have same instance variable? में चर्चा की गई है। (क्या होगा यदि पैरेंट वैरिएबल नाम बदल दिया गया है? तो यह अब और छायांकित नहीं होगा।) हालांकि, मैं अभी भी उत्सुक हूं कि अलग-अलग स्थिर/nonstatic भिन्नताएं एक-दूसरे को छायांकित करती हैं। एक तरफ मैं उम्मीद करता हूं कि वे एक ही वैरिएबल नाम हैं, इसलिए छाया हो जाएगी, लेकिन दूसरी तरफ ऐसा लगता है जैसे कंपाइलर स्थिरता के आधार पर दोनों के बीच अंतर कर सकता है।जावा में, यदि कोई बच्चा वर्ग एक स्थिर पैरेंट वैरिएबल को एक आवृत्ति बाल चर के साथ छाया करता है, तो कौन सा चर विरासत विधियों का उपयोग करेगा?

+1

मुझे लगता है कि यह कुछ विचार करना महत्वपूर्ण है और दूसरों की मदद कर सकते हैं, तो यह सवाल उपयोग की है, लेकिन: ** आप इसे करने की कोशिश है ** –

+4

यह एक बात है की कोशिश कर रहा है, लेकिन वह संकलक हो सकता है? निर्भर। मैं सोच रहा हूं कि भाषा विनिर्देश में इसके बारे में कोई निश्चित नियम है या नहीं। –

उत्तर

4

The Java Language Specification से:

एक अभिव्यक्ति नाम एक भी पहचानकर्ता के होते हैं, तो ठीक एक दिखाई घोषणा दर्शाने होना चाहिए या तो एक स्थानीय बिंदु पर चर, पैरामीटर या फ़ील्ड जिस पर पहचानकर्ता होता है। अन्यथा, एक संकलन-समय त्रुटि होती है।

घोषणा एक अंतिम क्षेत्र वाणी है, तो नाम का अर्थ कि फ़ील्ड का मान है। अन्यथा, अभिव्यक्ति नाम का अर्थ घोषणा द्वारा घोषित चर है।

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

इस उत्तर पूरी तरह से सवाल का मेरी नई समझ के आधार पर फिर से लिखा गया है। नीचे मेरा पहला जवाब है, जो वंश के लिए रखा गया है।

The Java Language Specification से

:

एक घोषणा एक क्षेत्र के घ, स्थानीय चर, विधि पैरामीटर, निर्माता पैरामीटर या अपवाद संचालक पैरामीटर n छाया किसी भी अन्य क्षेत्रों की घोषणाओं, स्थानीय नामित चर, विधि पैरामीटर, कन्स्ट्रक्टर पैरामीटर या अपवाद हैंडलर पैरामीटर नाम n जो उस बिंदु पर हैं जहां डी डी के दायरे में होता है।

यह बताता है कि स्थिरता के बावजूद कंपाइलरों को पैरेंट वैरिएबल को छाया करने की आवश्यकता होती है।

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

+1

यह वास्तव में एक उत्तर है जो मैं पूछने की कोशिश कर रहा था: "इनमें से कोई भी विरासत विधियों के लिए प्रासंगिक नहीं है, जो कि उप-वर्ग उन्हें छायांकित करता है या नहीं, इस पर ध्यान दिए बिना मूल चर का उपयोग करता है।" –

+0

क्या भाषा विनिर्देश यह कहता है? यदि हां, तो कहाँ? मैं इसे खोजने की कोशिश कर रहा हूं। –

+0

@DougTreadwell हाँ, यह करता है। मैंने अपना जवाब संपादित कर लिया है। – Taymon

0

नीचे दिए गए कोड को देखें। यदि आप ChildClass से field तक पहुंच चाहते हैं, तो यह अपने स्वयं के सदस्य चर का उपयोग करेगा। यदि आप SuperClass से स्थिर field तक पहुंच बनाना चाहते हैं, तो आपको इसे SuperClass.field का उपयोग कर स्पष्ट रूप से कॉल करना होगा। 'STATIC_FIELD`` को सीधे एक्सेस किया जा सकता है क्योंकि कंपाइलर के लिए कोई अस्पष्टता नहीं है।

public class SuperClass{ 
    static String field = "staticField1"; 
    static String STATIC_FIELD = "staticField2"; 

    //not possible to have a member field in this class -> compile error 
    //String field = "memberField"; is not possible 
    public SuperClass() { 
     System.out.println("field = " + field); 

    } 
    } 
    public class ChildClass extends SuperClass{ 
    String field = "memberField"; 

    public ChildClass() { 
     System.out.println("field = " + field);//access to member field 
     //need to explicitly call SuperClass.field to access the static variable 
     System.out.println("SuperClass.field = " + SuperClass.field); 
     //no need to do this when there is no amibiguity 
     System.out.println("STATIC_FIELD = " + STATIC_FIELD); 
    } 
    } 

भी देखें 15.11.1 और here में 15.11.2 और here

+0

मैं छायांकन के विचार को समझता हूं, लेकिन मेरे qusetion का महत्वपूर्ण हिस्सा "कौन सा चर विरासत विधियों का उपयोग करेगा?"। –

6

में 8.3 प्रति जावा भाषा विनिर्देश के रूप में: वर्ग घोषणा एक निश्चित नाम के साथ एक क्षेत्र वाणी है, तो

हैं उस क्षेत्र के को किसी भी और सभी वर्गों के सभी सुलभ घोषणाओं को छिपाने के लिए कहा जाता है सुपरक्लास में समान नाम और कक्षा के superinterfaces के साथ।

एक छिपे हुए क्षेत्र के लिए एक योग्य नाम का उपयोग कर (अगर यह स्थिर होता है) द्वारा पहुँचा जा सकता

JVM Specification

आप उल्लेख कर सकते हैं "फील्ड घोषणा" खंड।

+0

अभी तक यह सबसे अच्छे उत्तरों में से एक है, लेकिन ऐसा लगता है कि यह केवल छायांकन पर केंद्रित है। मैं किसी भी जानकारी को नहीं हटाऊंगा, लेकिन क्या विनिर्देशन में कुछ अतिरिक्त है जो इंगित करेगा कि विरासत विधियों ने बच्चे के खेतों का भी उपयोग किया है? –

+0

ऐसा लगता है कि आपको इसके लिए Taymon से जवाब मिला। इस उत्तर में – kosa

+0

+1 क्योंकि यह उल्लेख करता है कि आप अभी भी पूरी तरह से योग्य नाम के माध्यम से फ़ील्ड तक पहुंच सकते हैं। – Bill

4

वे करेंगे:

class Parent { 
    static String x="static in parent"; 
    String y="instance in parent"; 
} 
class Child extends Parent { 
    static String y="static in child"; 
    String x="instance in child"; 
    void foo() { 
     System.out.println("x "+x); 
     System.out.println("super.x " + super.x); 
     System.out.println("y "+y); 
     System.out.println("super.y " + super.y); 
    } 
} 
public class Main { 
    public static void main(String[] args) { 
     Parent parent=new Parent(); 
     Child child=new Child(); 
     System.out.println("Parent.x "+Parent.x); 
     System.out.println("parent.x "+Parent.x); 
     System.out.println("parent.y "+parent.y); 
     System.out.println("child.x "+child.x); 
     System.out.println("Child.y "+Child.y); 
     System.out.println("child.y "+child.y); 
     System.out.println("(Parent)child).x "+((Parent)child).x); 
     System.out.println("(Parent)child).y "+((Parent)child).y); 
     child.foo(); 
    } 
} 



Parent.x static in parent 
parent.x static in parent 
parent.y instance in parent 
child.x instance in child 
Child.y static in child 
child.y static in child 
(Parent)child).x static in parent 
(Parent)child).y instance in parent 
x instance in child 
super.x static in parent 
y static in child 
super.y instance in parent 
+1

आउटपुट भी पोस्ट करें, ताकि लोग यह जान सकें कि यह क्या करता है, या तो – Bohemian

+0

में चिपका हुआ आउटपुट, मैं छायांकन के विचार को समझता हूं, लेकिन मेरे क्यूसेटियन का महत्वपूर्ण हिस्सा "कौन सा चर विरासत विधियों का उपयोग करेगा? "। –

+0

कृपया –

0
public class Test { 

    public static int MYNUMBER = 5; 

    public Test() { 
    } 
} 

public class TestChild extends Test { 

    public int MYNUMBER = 8; 

    public TestChild() { 
    } 
} 

public class Main { 

    public static void main(String[] args) { 
     TestChild testChild = new TestChild(); 

     // This would print out 8 
     System.out.println("in main test child: " + testChild.MYNUMBER); 

     // This won't even compile if the MYNUMBER variable is overshadowed 
     // If the MYNUMBER variable is not overshadowed it 
     // would compile and 
     // print out 5 
     // If we make MYNUMBER static also on TestChild, 
     // it would compile and print out 8 
     System.out.println("in main TestChild.MYNUMBER " + TestChild.MYNUMBER); 

     // This would print out 5 
     System.out.println(Test.MYNUMBER); 
    } 

} 
+0

मैं छायांकन के विचार को समझता हूं, लेकिन मेरे qusetion का महत्वपूर्ण हिस्सा है "कौन सा चर विरासत विधियों का उपयोग करेगा ? "। –

+0

विरासत विधियों माता-पिता के स्थिर चर का उपयोग करेंगे। तो यदि हम टेस्ट क्लास में विधि जोड़ते हैं: सार्वजनिक int do कुछ() { \t \t वापसी MYNUMBER; \t} कुछ भी हर समय 5 लौटाएगा। – Alex

0

ग्रहण के कंपाइलर के साथ, अभिभावक वर्ग के तरीके अभी भी सुपरक्लास से सदस्य चर का उपयोग करेंगे, न कि बाल वर्ग से छायांकित चर, जैसा कि नीचे दिखाया गया है। यह Thinksteep के जवाब का एकमात्र थोड़ा संशोधित संस्करण है।

class Parent { 
    static String x ="static in parent"; 
    String y="instance in parent"; 

    void bar() { 
     System.out.println("x "+ x); 
     System.out.println("y "+ y); 
    } 
} 

class Child extends Parent { 
    static String y ="static in child"; 
    String x="instance in child"; 

    void foo() { 
     System.out.println("x "+x); 
     System.out.println("super.x " + super.x); 
     System.out.println("y "+y); 
     System.out.println("super.y " + super.y); 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
     Parent parent=new Parent(); 
     Child child=new Child(); 
     System.out.println("Parent.x "+Parent.x); 
     System.out.println("parent.x "+Parent.x); 
     System.out.println("parent.y "+parent.y); 
     System.out.println("child.x "+child.x); 
     System.out.println("Child.y "+Child.y); 
     System.out.println("child.y "+child.y); 
     System.out.println("(Parent)child).x "+((Parent)child).x); 
     System.out.println("(Parent)child).y "+((Parent)child).y); 
     System.out.println("Member variable visibility in parent:"); 
     parent.bar(); 
     System.out.println("Member variable visibility in child:"); 
     child.foo(); 
     System.out.println("Member variable visibility in inherited methods:");   
     child.bar(); 

     System.exit(0); 
} 

/* Output: 
Parent.x static in parent 
parent.x static in parent 
parent.y instance in parent 
child.x instance in child 
Child.y static in child 
child.y static in child 
(Parent)child).x static in parent 
(Parent)child).y instance in parent 
Member variable visibility in parent: 
x static in parent 
y instance in parent 
Member variable visibility in child: 
x instance in child 
super.x static in parent 
y static in child 
super.y instance in parent 
Member variable visibility in parent methods: 
x static in parent 
y instance in parent 
*/ 
संबंधित मुद्दे