2008-12-03 12 views
17

ठीक है, मेरे साथ लड़कों और लड़कियों के साथ भालू जैसा मैं सीख रहा हूं। मेरा सवाल यहाँ है।ओवरराइडिंग और विरासत के साथ सहायता

मुझे पता नहीं लगा सकता कि मैं अभिभावक वर्ग से किसी विधि को ओवरराइड क्यों नहीं कर सकता। बेस क्लास से कोड यहां दिया गया है (हां, मैंने ओओपी बुक से जावा कोड को पायलट किया है और इसे सी # में फिर से लिखने की कोशिश कर रहा हूं)।

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    public class SadObject: MoodyObject 
    { 
     protected String getMood() 
     { 
      return "sad"; 
     } 

     //specialization 
     public void cry() 
     { 
      Console.WriteLine("wah...boohoo"); 
     } 
    } 
} 

और::

using System; 

public class MoodyObject 
{ 
    protected String getMood() 
    { 
     return "moody"; 
    } 

    public void queryMood() 
    { 
     Console.WriteLine("I feel " + getMood() + " today!"); 
    } 
} 

और यहाँ मेरे अन्य 2 वस्तुओं है कि आधार वर्ग (MoodyObject) के वारिस हैं

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    public class HappyObject: MoodyObject 
    { 
     protected String getMood() 
     { 
      return "happy"; 
     } 

     public void laugh() 
     { 
      Console.WriteLine("hehehehehehe."); 
     } 
    } 
} 

और यहाँ अपने मुख्य है:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MoodyObject moodyObject = new MoodyObject(); 
      SadObject sadObject = new SadObject(); 
      HappyObject happyObject = new HappyObject(); 

      Console.WriteLine("How does the moody object feel today?"); 
      moodyObject.queryMood(); 
      Console.WriteLine(""); 
      Console.WriteLine("How does the sad object feel today?"); 
      sadObject.queryMood(); 
      sadObject.cry(); 
      Console.WriteLine(""); 
      Console.WriteLine("How does the happy object feel today?"); 
      happyObject.queryMood(); 
      happyObject.laugh(); 
     } 
    } 
} 

जैसा कि आप देख सकते हैं, सुंदर मूलभूत सामान, लेकिन एच ere का आउटपुट:

मूडी ऑब्जेक्ट आज कैसा महसूस करता है? मुझे आज मूडी लग रहा है!

दुखद वस्तु आज कैसा महसूस करती है? मैं आज मूडी महसूस करता हूँ! वाह ... बूहू

खुश वस्तु आज कैसा महसूस करती है? मुझे आज मूडी लग रहा है! hehehehehehe। जारी रखने के लिए कोई भी कुंजी दबाएं। । ।

नहीं के रूप में मैं उम्मीद थी। मैंने मूल विधि वर्चुअल बनाने और इसे ओवरराइड करने का प्रयास करते समय ओवरराइड करने का प्रयास किया है और यह मुझे यह त्रुटि प्राप्त करता है "विरासत सदस्य" MoodyObject.getMood() 'को ओवरराइड नहीं कर सकता क्योंकि यह वर्चुअल, सार, या ओवरराइड चिह्नित नहीं है "। मैंने आभासी और ओवरराइड के बिना भी कोशिश की और ऐसा लगता है कि मैं बेस विधि को छिपाने की कोशिश कर रहा हूं। फिर, मैं ओओपी के लिए नया हूं और किसी भी मार्गदर्शन की सराहना करता हूं।

जोड़ने के लिए संपादित: मैं यह मिल गया! "ConsoleAplication1" आइटम के विपरीत समाधान खोजकर्ता में MoodyObject.cs केवल "समाधान आइटम" था। मैंने इसे नीचे खींच लिया जहां यह समाधान एक्सप्लोरर और वॉयला में था! यह अब काम करता है। मैंने जवाब के रूप में नीचे ल्यूक का जवाब चिह्नित किया क्योंकि उसने उस सहायता की पेशकश की जहां मुझे यह हल करने के लिए आवश्यक था ... मैं यहां बहुत कुछ सीख रहा हूं। यह आश्चर्यजनक है और आप लोग और लड़कियां पागल स्मार्ट हैं!

+3

एक स्वीकार किए जाते हैं के रूप में मेरा उत्तर अंकन के लिए धन्यवाद, लेकिन मैं सुझाव है कि हो सकता है कि आप (जैसे इल्या या जोश के रूप में) मेरा एक से थोड़ा कम वर्बोज़ और साथ में अधिक जानकारी चुनें? –

+0

जैसा आप चाहें धन्यवाद फिर से ल्यूक – GregD

उत्तर

55

सी # तरीकों में इसलिए यदि आप overridable के रूप में कुछ विधि डिजाइन, डिफ़ॉल्ट रूप से आभासी नहीं हैं, आप आभासी रूप में यह निर्दिष्ट करना चाहिए:

class Base 
{ 
    protected virtual string GetMood() {...} 
} 

दूसरे, आप है कि आप से विधि ओवरराइड करने के लिए जा रहे हैं निर्दिष्ट करना व्युत्पन्न कक्षा में आधार वर्ग।

class Derived : Base 
{ 
    protected override string GetMood() {...} 
} 

आप "ओवरराइड" कीवर्ड निर्दिष्ट नहीं करते हैं, तो आप (के लिए विधि स्पष्ट रूप से ऐसा राज्य के लिए और संकलक से चेतावनी 'नई' कीवर्ड डालने के लिए) विधि है कि खाल आधार प्रकार मिल जाएगा।

आप विरासत श्रृंखला बंद करो और विधि की आगे ओवरराइड नामंज़ूर चाहते हैं, आप विधि के रूप में सील निशान चाहिए, इस तरह:

protected sealed override string GetMood() {...} 
1
public class SadObject: MoodyObject 
    { 
     override String getMood() 
+0

जब मैं इसे चलाने का प्रयास करता हूं तो मुझे यह त्रुटि मिलती है: "वर्चुअल या अमूर्त सदस्य निजी नहीं हो सकते हैं"।मैंने getMood बेस वर्चुअल और एक ही त्रुटि भी बनाई है। – GregD

+0

इसका मतलब है कि आपकी GetMood विधि निजी है और आपके प्रश्न में लिखी गई नहीं है। –

+0

हालांकि यह नहीं है। यह संरक्षित है। मैं कसम खाता हूँ :) – GregD

2

अपने विधि करके GetMood मूडी में virtual और व्युत्पन्न वर्ग में override, अपने कोड काम करना चाहिए। क्या आप वाकई इन खोजशब्दों को रखते हैं जहां वे संबंधित हैं?

public class MoodyObject 
{ 
    protected virtual String getMood() 
    { 
     return "moody"; 
    } 

    public void queryMood() 
    { 
     Console.WriteLine("I feel " + getMood() + " today!"); 
    } 
} 

public class SadObject : MoodyObject 
{ 
    protected override String getMood() 
    { 
     return "sad"; 
    } 

    //specialization 
    public void cry() 
    { 
     Console.WriteLine("wah...boohoo"); 
    } 
} 

public class HappyObject : MoodyObject 
{ 
    protected override String getMood() 
    { 
     return "happy"; 
    } 

    public void laugh() 
    { 
     Console.WriteLine("hehehehehehe."); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     MoodyObject moodyObject = new MoodyObject(); 
     SadObject sadObject = new SadObject(); 
     HappyObject happyObject = new HappyObject(); 

     Console.WriteLine("How does the moody object feel today?"); 
     moodyObject.queryMood(); 
     Console.WriteLine(""); 
     Console.WriteLine("How does the sad object feel today?"); 
     sadObject.queryMood(); 
     sadObject.cry(); 
     Console.WriteLine(""); 
     Console.WriteLine("How does the happy object feel today?"); 
     happyObject.queryMood(); 
     happyObject.laugh(); 

     Console.Read(); 
    } 
} 

हो सकता है कि अपनी गलती तथ्य यह है कि जावा में, सभी तरीकों आभासी है, जो मामला नहीं है से आता है सी # (के रूप में दान सी द्वारा बताया: यहाँ पूरा कोड, कि संकलित करता है तथा ठीक से चलाया जाता है ।)।

+0

मैंने कोशिश की है। जब मैं इसे चलाने का प्रयास करता हूं तो यह मुझे केवल यह त्रुटि प्राप्त करता है "त्रुटि 'ConsoleApplication1.HappyObject.getMood()': विरासत सदस्य 'MoodyObject.getMood()' को ओवरराइड नहीं कर सकता क्योंकि यह वर्चुअल, सार, या ओवरराइड चिह्नित नहीं है" – GregD

+0

क्या आप पूरी तरह से सुनिश्चित हैं कि आपने अपनी मूल विधि वर्चुअल के रूप में चिह्नित की है? मैंने अभी कोड की कोशिश की और यह पूरी तरह से ठीक काम किया। –

+0

यहां यह आपके लिए कट/पेस्ट किया गया है: सिस्टम का उपयोग कर; सार्वजनिक वर्ग मूडीऑब्जेक्ट { संरक्षित आभासी स्ट्रिंग getMood() { वापसी "मूडी"; } सार्वजनिक शून्य पूछताछ मूड() { कंसोल। राइटलाइन ("मुझे लगता है" + getMood() + "आज!"); } } – GregD

0

आपको "ओवरराइड" कीवर्ड के साथ getMood के ओवरराइड को चिह्नित करने की आवश्यकता है। आपको "वर्चुअल" कीवर्ड के साथ बेस getMood विधि को चिह्नित करने की भी आवश्यकता होगी।

5

जहां तक ​​मुझे पता है, जावा में सभी विधियां डिफ़ॉल्ट रूप से आभासी हैं। यह सी # के मामले में नहीं है, इसलिए आपको बेस वर्चुअल विधियों को "आभासी" के साथ चिह्नित करने की आवश्यकता है, उदा। protected virtual string getMood() ... और "ओवरराइड" के साथ ओवरराइड, उदा। protected override string getMood()...

3

आप एक आधार वर्ग विधि ओवरराइड करने के लिए चाहते हैं, यह virtual के रूप में घोषित किए जाने की जरूरत:

यहाँ वाक्य रचना आप की जरूरत के बारे में MSDN लेख है। व्युत्पन्न वर्ग में ओवरराइडिंग विधि को स्पष्ट रूप से override के रूप में घोषित किया जाना चाहिए। यह काम करना चाहिए:

public class BaseObject 
{ 
    protected virtual String getMood() 
    { 
     return "Base mood"; 
    } 

    //... 
} 

public class DerivedObject: BaseObject 
{ 
    protected override String getMood() 
    { 
     return "Derived mood"; 
    } 
    //... 
} 

संपादित करें: मैं सिर्फ एक ग # सांत्वना आवेदन में यह करने की कोशिश की, और यह संकलित करता है। इसलिए आपके द्वारा उपयोग किए जाने वाले स्रोत कोड को आपके द्वारा यहां पोस्ट किए गए कुछ छोटे लेकिन महत्वपूर्ण टुकड़ों में भिन्न होना चाहिए।

मेरे Program.cs यह है:

using System; 
using System.Collections.Generic; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     {  
      // leaving out your implementation to save space...  
     } 
    }  

    public class SadObject : MoodyObject 
    { 
     protected override String getMood() 
     { 
      return "sad"; 
     } 

     //specialization 
     public void cry() 
     { 
      Console.WriteLine("wah...boohoo"); 
     } 
    } 

    public class HappyObject : MoodyObject 
    { 
     protected override String getMood() 
     { 
      return "happy"; 
     } 

     public void laugh() 
     { 
      Console.WriteLine("hehehehehehe."); 
     } 
    } 
} 
+0

यह ठीक है कि मैंने इसे कैसे लिखा है – GregD

6

आप किसी भी सार तरीकों किसी भी आभासी ओवरराइड या लागू करने के लिए ओवरराइड कीवर्ड का उपयोग करने की जरूरत है।

public class MoodyObject 
{ 
    protected virtual String getMood() 
    { 
     return "moody"; 
    }  
    public void queryMood() 
    { 
     Console.WriteLine("I feel " + getMood() + " today!"); 
    } 
} 

public class HappyObject : MoodyObject 
{ 
    protected override string getMood() 
    { 
     return "happy"; 
    } 
} 

मैं यहां क्या अनुशंसा करता हूं कि आप संभवतः मूडी ऑब्जेक्ट के लिए एक अमूर्त वर्ग होने के लिए हैं। (यदि आप ऐसा करते हैं तो आपको अपनी मुख्य विधि बदलनी होगी, लेकिन आपको इसका पता लगाना चाहिए) क्या यह वास्तव में मूडी मोड में होना समझ में आता है? क्या हम ऊपर है के साथ समस्या यह है कि आपके HappyObject getMood.By एक वर्ग सार बनाने यह कई काम करता है के लिए एक कार्यान्वयन प्रदान करने के लिए आवश्यक नहीं है:

  1. आप कर सकते हैं अप कोई नई बात नहीं एक अमूर्त वर्ग का एक उदाहरण। आपको एक बाल वर्ग का उपयोग करना होगा।
  2. आप कुछ तरीकों को लागू करने के लिए व्युत्पन्न बच्चों को मजबूर कर सकते हैं।

तो यह करने के लिए आप अंत:

public abstract class MoodyObject 
{ 
    protected abstract String getMood(); 

    public void queryMood() 
    { 
     Console.WriteLine("I feel " + getMood() + " today!"); 
    } 
} 

नोट कैसे तुम अब getMood के लिए एक कार्यान्वयन प्रदान करते हैं।

+0

क्या होगा यदि मेरी आधार रेखा यह है कि मैं हमेशा मूडी हूं? तो आपके डिजाइन के साथ, मेरे पास तीन बच्चे वर्ग मूडी, खुश और उदास होंगे? – GregD

+0

हां, मुझे लगता है कि आपके मन में आपके मूड बेस क्लास के साथ एक मूड बेस क्लास होना चाहिए जो आप चाहते हैं कि प्रत्येक मूड के लिए। अगर मूडी एक मूड होने का मतलब है तो यह मेरी राय में आधार वर्ग नहीं होना चाहिए। – JoshBerke

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