2008-11-28 17 views
113

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

मैं तो मैं एक आधार वर्ग विधि में यह संदर्भित कर सकते हैं baseclass में यह निर्धारित करना चाहते हैं - उदाहरण के ToString अधिभावी कहने के लिए "यह ऑब्जेक्ट प्रकार संपत्ति/क्षेत्र की है" के लिए। मेरे पास तीन तरीके हैं जिन्हें मैं ऐसा करने के बारे में देख सकता हूं, लेकिन मैं सोच रहा था - ऐसा करने का सबसे अच्छा या स्वीकार्य तरीका क्या है? न्यूबी सवाल, क्षमा करें।

विकल्प 1:
उपयोग एक अमूर्त संपत्ति और इसे विरासत में मिला वर्गों पर ओवरराइड। लागू होने से यह लाभ (आपको इसे ओवरराइड करना होगा) और यह साफ़ है। लेकिन, एक क्षेत्र को encapsulate करने के बजाय एक हार्ड कोड मूल्य वापस करने के लिए थोड़ा गलत लगता है और यह सिर्फ बजाय कोड की कुछ पंक्तियों है। मुझे "सेट" के लिए एक शरीर घोषित करना है, लेकिन यह कम महत्वपूर्ण है (और संभवतः उस से बचने का एक तरीका है जिसे मैं नहीं जानता)।

abstract class Father 
{ 
    abstract public int MyInt { get; set;} 
} 

class Son : Father 
{ 
    public override int MyInt 
    { 
     get { return 1; } 
     set { } 
    } 
} 

विकल्प 2
मैं एक सार्वजनिक क्षेत्र (या एक संरक्षित क्षेत्र) घोषित करने और स्पष्ट रूप से विरासत में मिला कक्षा में यह ओवरराइड कर सकते हैं। नीचे दिया गया उदाहरण मुझे "नया" उपयोग करने की चेतावनी देगा और मैं शायद ऐसा कर सकता हूं, लेकिन यह गलत लगता है और यह बहुरूपता को तोड़ देता है, जो कि पूरी बात थी। एक अच्छा विचार की तरह प्रतीत नहीं होता ...

abstract class Mother 
{ 
    public int MyInt = 0; 
} 

class Daughter : Mother 
{ 
    public int MyInt = 1; 
} 

विकल्प 3
मैं एक संरक्षित क्षेत्र का उपयोग करें और निर्माता में मूल्य निर्धारित कर सकते हैं। यह बहुत साफ दिखता है लेकिन यह सुनिश्चित करता है कि कन्स्ट्रक्टर हमेशा इसे सेट करता है और एकाधिक अधिभारित कन्स्ट्रक्टरों के साथ हमेशा एक मौका होता है कि कुछ कोड पथ मूल्य निर्धारित नहीं करेंगे।

abstract class Aunt 
{ 
    protected int MyInt; 
} 

class Niece : Aunt 
{ 
    public Niece() 
    { 
     MyInt = 1; 
    } 
} 

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

उत्तर

107
तीन समाधान के

केवल विकल्प 1 के साथ समस्या यह है बहुरूपी है ।

स्वयं द्वारा फ़ील्ड ओवरराइड नहीं किया जा सकता है। यही कारण है कि विकल्प 2नया कीवर्ड चेतावनी देता है।

चेतावनी का हल 'नई' कीवर्ड संलग्न करने के लिए नहीं है, लेकिन विकल्प 1.

लागू करने के लिए आप अपने क्षेत्र की जरूरत है बहुरूपी आप एक संपत्ति में लपेट की जरूरत हो रहा है।

विकल्प 3 ठीक है यदि आपको पॉलीमोर्फिक व्यवहार की आवश्यकता नहीं है। आपको याद रखना चाहिए, कि जब रनटाइम पर संपत्ति MyInt का उपयोग किया जाता है, तो व्युत्पन्न वर्ग का मूल्य वापस लौटने पर कोई नियंत्रण नहीं होता है। आधार वर्ग स्वयं ही इस मूल्य को वापस करने में सक्षम है।

इस प्रकार आपकी संपत्ति का वास्तव में बहुरूप कार्यान्वयन हो सकता है, व्युत्पन्न कक्षाओं को नियंत्रण पर रखने की इजाजत दी जा सकती है।

abstract class Parent 
{ 
    abstract public int MyInt { get; } 
} 

class Father : Parent 
{ 
    public override int MyInt 
    { 
     get { /* Apply formula "X" and return a value */ } 
    } 
} 

class Mother : Parent 
{ 
    public override int MyInt 
    { 
     get { /* Apply formula "Y" and return a value */ } 
    } 
} 
+104

एक तरफ, मुझे सच में लगता है कि ** पिता ** फॉर्मूला "वाई", और मां, तार्किक रूप से, "एक्स" लागू करना चाहिए। –

0

मैं विकल्प 3 के साथ जाऊंगा, लेकिन एक सार सेट Myynt विधि है कि subclasses को लागू करने के लिए मजबूर किया जाता है। इस तरह आपको एक व्युत्पन्न वर्ग की समस्या नहीं होगी जिसे इसे निर्माता में सेट करना भूल जाए।

abstract class Base 
{ 
protected int myInt; 
protected abstract void setMyInt(); 
} 

class Derived : Base 
{ 
override protected void setMyInt() 
{ 
    myInt = 3; 
} 
} 

वैसे, विकल्प विकल्प के साथ, यदि आप सेट निर्दिष्ट नहीं करते हैं; आपके सार आधार वर्ग संपत्ति में, व्युत्पन्न वर्ग को इसे लागू नहीं करना होगा।

abstract class Father 
{ 
    abstract public int MyInt { get; } 
} 

class Son : Father 
{ 
    public override int MyInt 
    { 
     get { return 1; } 
    } 
} 
0

यदि आप निर्माता में संपत्ति के मूल्य की आवश्यकता होती है करने के लिए अपने सार आधार वर्ग को संशोधित विकल्प 3 के साथ जा सकते हैं, आप किसी भी पथ छूट न जाए। मैं वास्तव में इस विकल्प पर विचार करता हूँ।

abstract class Aunt 
{ 
    protected int MyInt; 
    protected Aunt(int myInt) 
    { 
     MyInt = myInt; 
    } 

} 

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

3

आप कुछ इस तरह निर्धारित कर सकते हैं:

abstract class Father 
{ 
    //Do you need it public? 
    protected readonly int MyInt; 
} 

class Son : Father 
{ 
    public Son() 
    { 
     MyInt = 1; 
    } 
} 

के रूप में केवल पढ़ने के लिए मूल्य की स्थापना करके, यह कि उस वर्ग के लिए मूल्य वस्तु के जीवन भर के लिए अपरिवर्तित रहता है सुनिश्चित करता है।

मुझे लगता है कि अगला प्रश्न यह है कि आपको इसकी आवश्यकता क्यों है?

+0

स्टेटिक शब्दों की एक खराब पसंद है क्योंकि इसका मतलब यह है कि मूल्य वर्ग के सभी उदाहरणों के बीच साझा किया जाता है, जो निश्चित रूप से नहीं है। –

+0

यह सच है। मैं इसे संपादित करूंगा। – Ant

15

विकल्प 2 एक गैर स्टार्टर है - आप नहीं ओवरराइड क्षेत्रों कर सकते हैं, आप कर सकते हैं केवल छिपाने उन्हें।

व्यक्तिगत रूप से, मैं हर बार विकल्प 1 के लिए जाऊंगा। मैं हर समय खेतों को निजी रखने की कोशिश करता हूं। ऐसा इसलिए है कि आपको वास्तव में संपत्ति को ओवरराइड करने में सक्षम होना चाहिए।

abstract class Mother 
{ 
    private readonly myInt; 
    public int MyInt { get { return myInt; } } 

    protected Mother(int myInt) 
    { 
     this.myInt = myInt; 
    } 
} 

class Daughter : Mother 
{ 
    public Daughter() : base(1) 
    { 
    } 
} 

शायद सबसे उपयुक्त तरीका है कि अगर मूल्य उदाहरण के जीवनकाल में परिवर्तन नहीं करता है: एक और विकल्प आधार वर्ग है जो एक निर्माता पैरामीटर से सेट किया गया है में केवल पढ़ने के लिए संपत्ति है।

+0

क्या हम अब यह http://msdn.microsoft.com/en-us/library/9fkccyh4.aspx के आधार पर सही नहीं कह सकते हैं msdn आलेख दिखाता है कि आप गुण – codingbiz

+1

@ कोडिंगबिज़ को ओवरराइड कर सकते हैं: मेरा उत्तर गुणों के बारे में कहां से बात करता है? फ़ील्ड और गुण एक ही चीज़ नहीं हैं। –

+0

@ कोडिंगबिज: (मेरा जवाब * अब * संपत्तियों के बारे में बात करता है, स्वीकार्य रूप से - लेकिन यह कभी नहीं कहा गया कि आप उन्हें ओवरराइड नहीं कर सके। यह कहता है - और कहता है कि आप * फ़ील्ड * को ओवरराइड नहीं कर सकते हैं, जो अभी भी सही है।) –

6

विकल्प 2 एक बुरा विचार है। इसके परिणामस्वरूप छायांकन कहा जाता है; असल में आपके पास दो अलग-अलग "मायआईंट" सदस्य हैं, एक मां में, और दूसरी बेटी में। इसके साथ समस्या यह है कि मां में लागू विधियों में मां की "माईन्ट" का संदर्भ दिया जाएगा, जबकि बेटी में लागू विधियों में बेटी की "मायआईंट" का संदर्भ दिया जाएगा। यह कुछ गंभीर पठनीयता मुद्दों, और बाद में लाइन के नीचे भ्रम पैदा कर सकता है।

व्यक्तिगत रूप से, मुझे लगता है कि सबसे अच्छा विकल्प 3 है; क्योंकि यह एक स्पष्ट केंद्रीकृत मूल्य प्रदान करता है, और अपने स्वयं के क्षेत्रों को परिभाषित करने की परेशानी के बिना बच्चों द्वारा आंतरिक रूप से संदर्भित किया जा सकता है - जो विकल्प 1.

3

आप इस

class x 
{ 
    private int _myInt; 
    internal virtual int myInt { get { return _myInt; } set { _myInt = value; } } 
} 

class y : x 
{ 
    private int _myYInt; 
    public override int myInt { get { return _myYInt; } set { _myYInt = value; } } 
} 

आभासी कर सकता है आप एक संपत्ति एक शरीर है कि कुछ उप-वर्गों इसे ओवरराइड करने देता है और अभी भी मिलता है।

0

मैं इस किया था ...

namespace Core.Text.Menus 
{ 
    public abstract class AbstractBaseClass 
    { 
     public string SELECT_MODEL; 
     public string BROWSE_RECORDS; 
     public string SETUP; 
    } 
} 

namespace Core.Text.Menus 
{ 
    public class English : AbstractBaseClass 
    { 
     public English() 
     { 
      base.SELECT_MODEL = "Select Model"; 
      base.BROWSE_RECORDS = "Browse Measurements"; 
      base.SETUP = "Setup Instrument"; 
     } 
    } 
} 

इस तरह से आप अभी भी फ़ील्ड का उपयोग कर सकते हैं।

+0

मुझे लगता है कि यह प्रोटोटाइप या डेमोइंग के लिए एक विज्ञापन-समाधान समाधान के रूप में अच्छा है। – Zimano

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