इसे परिभाषित करने के लिए बेस क्लास फोर्स प्रोग्रामर में सार संपत्ति


10

मैं एक एम्बेडेड डिवाइस के लिए एक राज्य पैटर्न के साथ कोडिंग कर रहा हूं। मेरे पास एक आधार / सार वर्ग है जिसे राज्य कहा जाता है और फिर प्रत्येक असतत (ठोस) राज्य वर्ग सार राज्य वर्ग को लागू करता है।

राज्य कक्षा में मेरे पास कई सार विधियां हैं। यदि मैं असतत (ठोस) वर्ग में सार विधियों को लागू नहीं करता हूं, तो विज़ुअल स्टूडियो इस तरह से कुछ त्रुटि देगा:

... त्रुटि 1 'myConcreteState' विरासत में मिला अमूर्त सदस्य 'myAbstractState' लागू नहीं करता है

अब: मैं StateName नामक प्रत्येक राज्य के लिए एक स्ट्रिंग संपत्ति बनाने की कोशिश कर रहा हूँ। जब भी मैं एक नया ठोस वर्ग बनाता हूं, मुझे StateName को परिभाषित करने की आवश्यकता होती है। मैं चाहता हूँ कि अगर मैं इसका इस्तेमाल नहीं करता तो VS एक त्रुटि फेंक सकता है। क्या ऐसा करने के लिए एक सरल तरीका है?

मैंने इसे सार / आधार वर्ग में आज़माया है:

public abstract string StateName { get; set; }

लेकिन मुझे प्रत्येक राज्य में गेट और सेट के तरीकों को लागू करने की आवश्यकता नहीं है।

संशोधित प्रश्न: एक आदर्श स्थिति में, प्रत्येक राज्य वर्ग को StateName परिभाषित करने और सार आधार वर्ग से विरासत में प्राप्त करने की आवश्यकता होगी।

StateName = "MyState1"; //or whatever the state's name is

यदि वह कथन गायब है, तो विज़ुअल स्टूडियो ऊपर वर्णित के अनुसार एक त्रुटि उत्पन्न करेगा। क्या यह संभव है और यदि ऐसा हो तो कैसे?


2
मुझे सवाल समझ नहीं आ रहा है।
बेन आरोनसन

मुझे लगता है कि ऐसा करने का "सही" तरीका बेस क्लास पर एक संरक्षित कंस्ट्रक्टर है जिसमें एक पैरामीटर के रूप में राज्य के नाम की आवश्यकता होती है।
रोमन रेनर

@RomanReiner मैंने ऐसा करने के बारे में सोचा था..लेकिन यह बेमानी लगता है क्योंकि हर बार किसी राज्य को बदलने / कॉल करने पर मुझे नाम लिखना होगा।
गिसमोक्स

@BenAaronson मैंने नीचे के पास अपना प्रश्न स्पष्ट किया है।
गिस्मोक्स

क्या राज्य का नाम प्रति प्रकार स्थिर या प्रति उदाहरण स्थिर है?
रोमन रेनर

जवाबों:


16

मुझे लगता है कि ऐसा करने का "सही" तरीका बेस क्लास पर एक संरक्षित कंस्ट्रक्टर है जिसमें एक पैरामीटर के रूप में राज्य के नाम की आवश्यकता होती है।

public abstract class State
{
    private readonly string _name;

    protected State(string name)
    {
        if(String.IsNullOrEmpty(name))
            throw new ArgumentException("Must not be empty", "name");

        _name = name;
    }

    public string Name { get { return _name; } }
}

ठोस राज्य तब एक सार्वजनिक कंस्ट्रक्टर प्रदान करते हैं, जो उचित नाम के साथ बेस क्लास कंस्ट्रक्टर को बुलाता है।

public abstract class SomeState : State
{
    public SomeState() : base("The name of this state")
    {
        // ...
    }
}

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

ध्यान दें कि जब आप एक ठोस स्थिति का ध्यान रखते हैं, तो आपको वह नाम प्रदान करने की आवश्यकता नहीं होती है क्योंकि इसका निर्माण करने वाले का ध्यान रखा जाता है:

var someState = new SomeState(); // No need to define the name here
var name = someState.Name; // returns "The name of this state"

1
धन्यवाद! वास्तव में, मेरा आधार वर्ग निर्माता अब एक अतिरिक्त तर्क लेता है; इसलिए मेरे पास दो इनपुट हैं। जैसे ही मैंने इसे स्थापित किया, मुझे त्रुटियाँ मिलीं कि मुझे राज्य श्रेणी के निर्माणकर्ताओं में एक अतिरिक्त तर्क की आवश्यकता है ...:base(arg1, arg2)! यह एक समाधान है जिसकी मुझे तलाश थी। यह वास्तव में मेरे राज्य को अधिक सुसंगत रखने में मदद करता है।
गिस्मोक्स

3

C # 6 के रूप में (मेरा मानना ​​है - C #: द न्यू एंड इम्प्रूव्ड C # 6.0 ) आप गेटटर केवल गुण बनाने में सक्षम हैं। तो आप अपने आधार वर्ग को इस तरह घोषित कर सकते हैं -

public abstract class State
{
    public abstract string name { get; }

    // Your other functions....
}

और फिर अपने उप-वर्ग में आप ऐसा लागू कर सकते हैं State-

public class SomeState : State
{
    public override string name { get { return "State_1"; } }
}

या लैम्ब्डा ऑपरेटर का उपयोग करके भी neater -

public class SomeState : State
{
    public override string name => "State_1";
}

दोनों हमेशा "State_1" लौटाएंगे और अपरिवर्तनीय होंगे।


1
यह लिखा जा सकता है, public override string name { get; } = "State_1";जिसके बाद हर बार मूल्य का पुनर्मूल्यांकन करने की आवश्यकता नहीं होती है।
डेव कजिनो

2

आपकी आवश्यकताएं एक विरोधाभास हैं:

मैं StateName नामक प्रत्येक राज्य के लिए एक स्ट्रिंग संपत्ति बनाने की कोशिश कर रहा हूँ ।

बनाम

लेकिन मुझे हर राज्य में इसे लागू करने की जरूरत नहीं है

कोई भाषा सुविधा नहीं है जो आपको केवल कुछ उप वर्गों में सदस्य के अस्तित्व को मजबूर करने की अनुमति देती है। आखिरकार, सुपर क्लास का उपयोग करने का उद्देश्य इस तथ्य पर भरोसा करना है कि सभी उपवर्गों में सुपर क्लास के सभी सदस्य होंगे (और संभवतः अधिक)। यदि आप ऐसी कक्षाएं बनाना चाहते हैं जो एक के रूप में कार्य करती हैं, Stateलेकिन एक नाम नहीं है, तो परिभाषा के अनुसार, उन्हें (/ कर सकते हैं) उपवर्ग नहीं होना चाहिए State

आपको या तो अपनी आवश्यकताओं को बदलना होगा या साधारण विरासत के अलावा कुछ का उपयोग करना होगा।

कोड के साथ एक संभावित समाधान जैसा कि Stateगैर सार में विधि बनाने और खाली स्ट्रिंग वापस करने के लिए हो सकता है ।


मुझे लगता है कि आपने उस दूसरे बयान को संदर्भ से बाहर ले लिया, लेकिन मैं स्पष्ट करूंगा। मुझे गेट / सेट विधियों की आवश्यकता नहीं है, मैं बस StateName = "MyState1"प्रत्येक राज्य में चाहता हूं । यदि मेरे पास स्टेट क्लास में वह स्टेटमेंट नहीं है, तो आदर्श रूप से विज़ुअल स्टूडियो एक त्रुटि उत्पन्न करेगा।
गिस्मोक्स

3
@GisMofx यदि आप प्रत्येक उपवर्ग में राज्य के नाम को लागू करना चाहते हैं, तो सार प्राप्त करें, लेकिन राज्य की आवश्यकता नहीं है। फिर प्रत्येक उपवर्ग return "MyState1"को उनके कार्यान्वयन के रूप में प्रदान करना होगा , और यदि उन्हें इसकी आवश्यकता है तो मूल्य के लिए परिवर्तनशील भंडारण जोड़ सकते हैं। लेकिन आपको प्रश्न में आवश्यकताओं को स्पष्ट करने की आवश्यकता है - क्या हर प्रकार के राज्य के लिए एक स्टेटनाम की आवश्यकता होती है जिसे पढ़ा जा सकता है, और क्या किसी भी प्रकार के राज्य को निर्माण के बाद इसे बदलने की आवश्यकता होती है?
पीट किर्कम

@PeteKirkham प्रत्येक राज्य को एक नाम की आवश्यकता है, इसे निर्माण के बाद उत्परिवर्तित नहीं किया जाना चाहिए। राज्यों के नाम स्थिर / अपरिवर्तनीय हैं।
गिस्मोक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.