2012-11-10 25 views
11

मान लीजिए कि जावा इन श्रेणीबद्ध वर्ग हैं चलो: जब मैं जावा निष्पादितजावा विरासत बनाम सी # विरासत

using System; 
class A 
{ 
} 
class B : A 
{ 
    public void M() 
    { 
     Console.WriteLine("B"); 
    } 
} 
class C : B 
{ 
    public void M() // I need to use public new void M() to avoid the warning 
    { 
     Console.WriteLine("C"); 
    } 
} 
class D : C 
{ 
    public static void Main(String[] args) 
    { 
     A a = new D(); 
     // a.M(); // doesn't work  
     B b = new D(); 
     b.M(); 
     C c = new D(); 
     c.M(); 
     D d = new D(); 
     d.M(); 
    } 
} 

:

class A 
{ 
} 
class B extends A 
{ 
    public void m() 
    { 
     System.out.println("B\n"); 
    } 
} 
class C extends B 
{ 
    public void m() 
    { 
     System.out.println("C\n"); 
    } 
} 
class D extends C 
{ 
    public static void main(String[] args) 
    { 
     A a = new D(); 
     // a.m(); // doesn't work 
     B b = new D(); 
     b.m(); 
     C c = new D(); 
     c.m(); 
     D d = new D(); 
     d.m(); 
    } 
} 

यह (अंधा) सी # में एक ही कोड के दोहराव है कोड, मुझे C-C-C मिला जबकि सी # रिटर्न B-C-C

मेरे लिए सी # का परिणाम अधिक समझ में आता है, क्योंकि संदर्भ बी अपनी विधि को आमंत्रित करता है।

  • C-C-C बजाय B-C-C मुद्रित करने के लिए जावा डिजाइनर के फैसले के पीछे तर्क क्या है? मेरा मतलब है, क्यों संदर्भ बी सी में ओवरराइडिंग विधि का उपयोग करता है? इस दृष्टिकोण का क्या फायदा है?
  • सी # करता है जैसे B-C-C प्रिंट करने के लिए मैं जावा कोड कैसे बदल सकता हूं? मेरा मतलब है, मैं जावा को सटीक संदर्भ की विधि का आह्वान करने के लिए कैसे सिखा सकता हूं?
  • C-C-C प्रिंट करने के लिए मैं सी # कोड कैसे बदल सकता हूं? मेरा मतलब है, ओवरराइडिंग विधि का आह्वान करने के लिए मैं सी # कैसे सिखा सकता हूं?
+2

यह एक साधारण डिजाइन मुद्दा है - जावा डिफ़ॉल्ट रूप से गतिशील प्रेषण का उपयोग करता है, जबकि सी # नहीं करता है, गतिशील प्राप्त करने के लिए सी # में प्रेषण आपको एक विधि वर्चुअल घोषित करने की आवश्यकता है और इंगित करता है कि ओवरराइडिंग विधि वास्तव में इसे ओवरराइड कर रही है। – amit

+1

डी और ए कक्षाओं में कोई समारोह नहीं है।आप उन्हें एक छोटी (स्पष्ट) नमूने के लिए छोड़ सकते हैं। जवाब के लिए –

उत्तर

10

यह virtual function परिभाषा के लिए है:

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

सी # में, आप क्रम में आभासी के रूप में प्रणाली की घोषणा करना चाहिए के रूप में MSDN में दिखाया गया है:

के बाद से M विधि आभासी नहीं है, यह b.M() निष्पादित करेगा, भले ही b चर वास्तव में एकहैउदाहरण।

जावा में, हर विधि डिफ़ॉल्ट रूप से आभासी है, तो आप आप एक विधि को ओवरराइड जब (यहां तक ​​कि @Override एनोटेशन के बिना) b.M() के व्यवहार d.M() कि c.M() विधि व्यवहार को विरासत में हो जाएगा।

मैं सी # करता है जैसे बी-सी-सी प्रिंट करने के लिए जावा कोड कैसे बदल सकता हूं? मेरा मतलब है, मैं जावा को सटीक संदर्भ की विधि का आह्वान करने के लिए कैसे सिखा सकता हूं?

आप जावा में ऐसा नहीं कर सकते हैं। MC कक्षा में विधि में M विधि को ओवरराइड कर देगी। finalB#M में संशोधक को जोड़ने से C या अन्य B बच्चे M() विधि को ओवरराइड नहीं कर सकते हैं।

सी-सी-सी प्रिंट करने के लिए मैं सी # कोड कैसे बदल सकता हूं? मेरा मतलब है, ओवरराइडिंग विधि का आह्वान करने के लिए मैं सी # कैसे सिखा सकता हूं?

बदलें virtual को B कक्षा में M विधि और C कक्षा में इसे ओवरराइड:

class B : A 
{ 
    public virtual void M() 
    { 
     Console.WriteLine("B"); 
    } 
} 
class C : B 
{ 
    public override void M() // I need to use public new void M() to avoid the warning 
    { 
     Console.WriteLine("C"); 
    } 
} 
6
  1. जावा में तरीकों के सभी डिफ़ॉल्ट रूप से आभासी है। और व्युत्पन्न कक्षाओं में विधियां बेस से विधियों को ओवरराइड करती हैं। सी # में वे नहीं हैं।

  2. ऐसा लगता है कि आप ऐसा नहीं कर सकते हैं। लेकिन आप व्युत्पन्न कक्षाओं को final के रूप में घोषित करके इस विधि को ओवरराइड करने से रोक सकते हैं।

  3. बेस क्लास में virtual कीवर्ड के साथ इस विधि को घोषित करें और व्युत्पन्न में override के साथ घोषित करें।

+0

+1 लेकिन यह अच्छा होगा अगर आप ग # इसके साथ निर्दिष्ट किया जा रहा के साथ अपने 3 बिंदु अलग तरीके से व्यक्त – exexzian

+3

आप बस B.m() अंतिम रूप में घोषित नहीं कर सकते हैं के रूप में यह C.m पाएगा() ओवरराइड कर। – prosseek

+0

वास्तव में @prosseek। मेरी गलती। संपादित। – 2kay

0

सी-सी-सी मुद्रित करने के लिए बी-सी-सी के बजाय जावा डिजाइनर के फैसले के पीछे तर्क क्या है? मेरा मतलब है, क्यों संदर्भ बी सी में ओवरराइडिंग विधि का उपयोग करता है? इस दृष्टिकोण का क्या फायदा है?

देखो कि आप डी क्लास ऑब्जेक्ट से विधि को कॉल करते हैं जो सी कक्षा से एम विधि विरासत में मिला है। संदर्भ प्रकार जावा में कोई फर्क नहीं पड़ता - महत्वपूर्ण हिस्सा यह है कि किस वर्ग ने ऑब्जेक्ट का संदर्भ दिया है।

1

बी-सी-सी के बजाय सी-सी-सी प्रिंट करने के जावा डिजाइनर के निर्णय के पीछे तर्क क्या है?

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

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

(नायब। कोई सही गलत यहाँ है या, प्रत्येक दृष्टिकोण अपने फायदे और नुकसान हैं।)

मैं कैसे बी सी सी बाहर मुद्रित करने के लिए सी # जैसे करता जावा कोड बदल सकते हैं?

उन्हें final घोषित करें।

सी-सी-सी प्रिंट करने के लिए मैं सी # कोड कैसे बदल सकता हूं?

उन्हें virtual या वर्ग को परिभाषित करता है कि उन्हें (प्रश्न में B) में abstract, और override घोषित बच्चे कक्षाओं में।

+0

आप '' override' साथ C' की विधि को चिह्नित करने की जरूरत है। – CodesInChaos

+0

@CodesInChaos वास्तव में, यह भी याद है कि सार आभासी निकलता है। – Richard

संबंधित मुद्दे