यह संभव है
tl; dr - यदि आप चाहते हैं तो आप सेटर के साथ केवल-प्राप्त विधि को ओवरराइड कर सकते हैं। यह मूल रूप से सिर्फ:
एक ऐसी newसंपत्ति बनाएं जिसमें एक getऔर एक setही नाम का उपयोग किया गया हो।
यदि आप कुछ और नहीं करते हैं, तो पुरानी getपद्धति को तब भी कहा जाएगा जब व्युत्पन्न वर्ग को उसके आधार प्रकार के माध्यम से बुलाया जाता है। इसे ठीक करने के लिए, एक abstractमध्यवर्ती परत जोड़ें जो overrideपुरानी getपद्धति का उपयोग करता है और इसे नई getविधि के परिणाम को वापस करने के लिए मजबूर करता है ।
यह हमें संपत्तियों को ओवरराइड करने में सक्षम बनाता है get/ setभले ही उनकी आधार परिभाषा में कोई कमी हो।
बोनस के रूप में, आप चाहें तो रिटर्न प्रकार भी बदल सकते हैं।
यदि आधार की परिभाषा get-only थी, तो आप अधिक व्युत्पन्न रिटर्न प्रकार का उपयोग कर सकते हैं।
यदि आधार की परिभाषा थी set, तो आप हमें कम व्युत्पन्न रिटर्न प्रकार दे सकते हैं।
यदि आधार परिभाषा पहले से ही थी get/ है set, तो:
सभी मामलों में, आप चाहें तो एक ही रिटर्न प्रकार रख सकते हैं। नीचे दिए गए उदाहरण सादगी के लिए समान रिटर्न प्रकार का उपयोग करते हैं।
स्थिति: पहले से मौजूद मौजूदा getसंपत्ति
आपके पास कुछ वर्ग संरचना है जिसे आप संशोधित नहीं कर सकते हैं। शायद यह सिर्फ एक वर्ग है, या यह पहले से मौजूद वंशानुक्रम का पेड़ है। जो भी हो, आप setएक संपत्ति में एक विधि जोड़ना चाहते हैं, लेकिन नहीं कर सकते।
public abstract class A // Pre-existing class; can't modify
{
public abstract int X { get; } // You want a setter, but can't add it.
}
public class B : A // Pre-existing class; can't modify
{
public override int X { get { return 0; } }
}
समस्या: नहीं कर सकते के साथ -only /overridegetgetset
आप overrideएक get/ setसंपत्ति के साथ चाहते हैं, लेकिन यह संकलन नहीं करेगा।
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
समाधान: एक abstractमध्यवर्ती परत का उपयोग करें
जब आप सीधे overrideएक get/ setसंपत्ति के साथ नहीं कर सकते , तो आप कर सकते हैं :
एक ही नाम से एक new get/ setसंपत्ति बनाएँ ।
overrideसंगति सुनिश्चित getकरने के लिए नई getविधि के लिए एक सहायक के साथ पुरानी विधि ।
तो, पहले आप abstractमध्यवर्ती परत लिखते हैं :
public abstract class C : B
{
// Seal off the old getter. From now on, its only job
// is to alias the new getter in the base classes.
public sealed override int X { get { return this.XGetter; } }
protected abstract int XGetter { get; }
}
फिर, आप उस वर्ग को लिखते हैं जो पहले संकलित नहीं किया गया था। यह इस बार संकलित करेगा क्योंकि आप वास्तव में override' getएन-प्रॉपर्टी ' नहीं कर रहे हैं; इसके बजाय, आप इसे newकीवर्ड का उपयोग करके बदल रहे हैं ।
public class D : C
{
private int _x;
public new virtual int X { get { return this._x; } set { this._x = value; } }
// Ensure base classes (A,B,C) use the new get method.
protected sealed override int XGetter { get { return this.X; } }
}
परिणाम: सब कुछ काम करता है!
जाहिर है, इस काम के लिए के रूप में इरादा है D।
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
test.X = 7;
Print(test.X); // Prints "7", as intended.
सब कुछ अभी भी काम करता है, जब Dइसका आधार कक्षाओं में से एक के रूप में देखा जाता है, जैसे Aया B। लेकिन, यह क्यों काम करता है इसका कारण थोड़ा कम स्पष्ट हो सकता है।
var test = new D() as B;
//test.X = 7; // This won't compile, because test looks like a B,
// and B still doesn't provide a visible setter.
हालाँकि, बेस क्लास की परिभाषा getअभी भी अंततः व्युत्पन्न वर्ग की परिभाषा से ओवरराइड है get, इसलिए यह अभी भी पूरी तरह से सुसंगत है।
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
var baseTest = test as A;
Print(test.X); // Prints "7", as intended.
विचार-विमर्श
यह विधि आपको -only गुणों के लिए setतरीकों को जोड़ने की अनुमति देती है get। आप इसका उपयोग सामान की तरह करने के लिए भी कर सकते हैं:
किसी भी संपत्ति को एक getएकल वर्ग में बदलें , चाहे वह set, या get-और- setसंपत्ति, चाहे वह किसी आधार वर्ग में हो।
व्युत्पन्न वर्गों में एक विधि का वापसी प्रकार बदलें।
मुख्य कमियां यह हैं कि करने के लिए अधिक कोडिंग है और abstract classविरासत के पेड़ में एक अतिरिक्त है। यह उन कंस्ट्रक्टरों के लिए थोड़ा कष्टप्रद हो सकता है जो पैरामीटर लेते हैं क्योंकि उन्हें मध्यवर्ती परत में कॉपी / पेस्ट करना पड़ता है।