खुद को संशोधित करने के बाद एक वर्ग की विधि को एक ही उदाहरण कब वापस करना चाहिए?


9

मेरे पास एक वर्ग है जिसमें तीन विधियां हैं A(), B()और C()। वे विधियाँ स्वयं के उदाहरण को संशोधित करती हैं।

जबकि विधियों को एक उदाहरण लौटना पड़ता है जब उदाहरण एक अलग प्रति है (बस के रूप में Clone()), मुझे वापसी के voidलिए एक ही विकल्प मिला है या उसी उदाहरण ( return this;) को विधि में एक ही उदाहरण को संशोधित करते समय और किसी अन्य मूल्य को वापस नहीं किया जाता है।

जब उसी संशोधित उदाहरण को वापस करने का निर्णय लिया जाता है, तो मैं नीच विधि श्रृंखलाएं कर सकता हूं जैसे obj.A().B().C();

क्या ऐसा करने का एकमात्र कारण यही होगा?

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

जवाबों:


7

चैनिंग का उपयोग कब करें

फंक्शन चेनिंग ज्यादातर उन भाषाओं के साथ लोकप्रिय है, जहां ऑटो-कम्प्लीट के साथ आईडीई आम जगह है। उदाहरण के लिए, लगभग सभी C # डेवलपर Visual Studio का उपयोग करते हैं। इसलिए, यदि आप C # के साथ विकसित कर रहे हैं, तो अपने तरीकों को जोड़ते हुए, उस वर्ग के उपयोगकर्ताओं के लिए समय बचाने वाला हो सकता है क्योंकि Visual Studio श्रृंखला बनाने में आपकी सहायता करेगा।

दूसरी ओर, PHP जैसी भाषाएं जो प्रकृति में अत्यधिक गतिशील हैं और अक्सर आईडीई में ऑटो-पूर्ण समर्थन नहीं होता है, वे कम कक्षाएं देखती हैं जो पीछा करने का समर्थन करती हैं। चेनपिंग विधियों को उजागर करने के लिए सही phpDocs कार्यरत होने पर ही चेनिंग उचित होगी।

जंजीर क्या है?

Fooनिम्नलिखित दो विधियों के नाम वाले एक वर्ग को देखते हुए दोनों श्रृंखलाबद्ध हैं।

function what() { return this; }
function when() { return new Foo(this); }

तथ्य यह है कि एक वर्तमान उदाहरण के लिए एक संदर्भ है, और एक नया उदाहरण बनाता है यह परिवर्तन नहीं करता है कि ये श्रृंखलाबद्ध तरीके हैं।

कोई स्वर्ण नियम नहीं है कि एक श्रृंखला योग्य विधि केवल वर्तमान वस्तु को संदर्भित करना चाहिए। वास्तव में, श्रव्य तरीके दो अलग-अलग वर्गों में हो सकते हैं। उदाहरण के लिए;

class B { function When() { return true; } };
class A { function What() { return new B(); } };

var a = new A();
var x = a.What().When();

thisउपरोक्त किसी भी उदाहरण में कोई संदर्भ नहीं है । कोड a.What().When()एक जंजीर का एक उदाहरण है। मजे की बात यह है कि वर्ग प्रकार Bको एक चर के लिए कभी नहीं सौंपा गया है।

एक विधि जंजीर है जब यह वापसी मूल्य एक अभिव्यक्ति के अगले घटक के रूप में इस्तेमाल किया जाता है।

यहाँ कुछ और उदाहरण हैं

 // return value never assigned.
 myFile.Open("something.txt").Write("stuff").Close();

// two chains used in expression
int x = a.X().Y() * b.X().Y();

// a chain that creates new strings
string name = str.Substring(1,10).Trim().ToUpperCase();

कब इस्तेमाल करें thisऔरnew(this)

अधिकांश भाषाओं में तार अपरिवर्तनीय हैं। इसलिए चाइनिंग मेथड कॉल में हमेशा नए तार पैदा होते हैं। जहाँ StringBuilder जैसी वस्तु को संशोधित किया जा सकता है।

संगति सर्वोत्तम अभ्यास है।

यदि आपके पास ऐसी विधियाँ हैं जो किसी वस्तु की स्थिति को संशोधित करती हैं और वापस आती हैं this, तो उन विधियों में मिश्रण न करें जो नए उदाहरण लौटाते हैं। इसके बजाय, एक विशिष्ट विधि बनाएं जिसे Clone()यह स्पष्ट रूप से करना होगा।

 var x  = a.Foo().Boo().Clone().Foo();

यह बहुत स्पष्ट है कि अंदर क्या चल रहा है a

बाहर कदम और पीछे की चाल

मैं इसे स्टेप आउट और बैक ट्रिक कहता हूं , क्योंकि यह चेनिंग से जुड़ी कई आम समस्याओं को हल करता है। इसका मूल रूप से मतलब है कि आप मूल वर्ग से एक नए अस्थायी वर्ग में कदम रखते हैं और फिर मूल कक्षा में वापस आ जाते हैं।

अस्थायी वर्ग केवल मूल वर्ग को विशेष सुविधाएँ प्रदान करने के लिए मौजूद है, लेकिन केवल विशेष परिस्थितियों में।

अक्सर ऐसे समय होते हैं जब एक श्रृंखला को राज्य बदलने की आवश्यकता होती है , लेकिन वर्ग Aउन सभी संभावित राज्यों का प्रतिनिधित्व नहीं कर सकता है । इसलिए एक श्रृंखला के दौरान एक नया वर्ग पेश किया जाता है जिसमें एक संदर्भ वापस होता है A। यह प्रोग्रामर को एक राज्य में वापस जाने और वापस करने की अनुमति देता है A

यहाँ मेरा उदाहरण है, विशेष राज्य के रूप में जाना जाता है B

class A {
    function Foo() { return this; }
    function Boo() { return this; }
    function Change() return new B(this); }
}

class B {
    var _a;
    function (A) { _a = A; }
    function What() { return this; }
    function When() { return this; }
    function End() { return _a; }
}

var a = new A();
a.Foo().Change().What().When().End().Boo();

अब यह एक बहुत ही सरल उदाहरण है। यदि आप अधिक नियंत्रण रखना चाहते थे, तो Bएक नए सुपर-प्रकार पर लौट सकते थे Aजिसमें अलग - अलग विधियां हैं।


4
मुझे वास्तव में समझ में नहीं आता है कि आप पूरी तरह से इन्टेलिसेंस जैसे स्वत: पूर्ण समर्थन के आधार पर विधि-निर्धारण की सलाह क्यों देते हैं। विधि श्रृंखला या धाराप्रवाह इंटरफेस किसी भी ओओपी भाषा के लिए एक एपीआई डिजाइन पैटर्न हैं; केवल एक चीज जो स्वत: पूर्ण होती है वह है टाइपोस और प्रकार की त्रुटियों को रोकना।
आमोन

@amon तुम गलत हो जो मैंने कहा। मैंने कहा कि यह अधिक लोकप्रिय है जब एक भाषा के लिए अंतर्मुखता सामान्य है। मैंने कभी नहीं कहा कि यह फीचर पर निर्भर था।
रिएक्टगुलर

3
हालांकि यह उत्तर मुझे जंजीर की संभावनाओं को समझने में बहुत मदद करता है, फिर भी मुझे इस बात की कमी है कि मैं कब जंजीर का इस्तेमाल करूं। यकीन है, निरंतरता सबसे अच्छा है । हालाँकि, मैं उस मामले का उल्लेख कर रहा हूं जब मैं फ़ंक्शन में अपनी ऑब्जेक्ट को संशोधित करता हूं और return this। मैं अपने पुस्तकालयों के उपयोगकर्ताओं को इस स्थिति को संभालने और समझने में कैसे मदद कर सकता हूं? (उन्हें श्रृंखला विधियों के लिए अनुमति देते हुए, जब भी इसकी आवश्यकता नहीं होती है, क्या यह वास्तव में ठीक होगा? या क्या मुझे केवल एक ही तरह से रहना चाहिए, बिल्कुल बदलने की आवश्यकता है?)
मार्टिन ब्रौन

@modiX अगर मेरा उत्तर सही है, तो कृपया इसे उत्तर के रूप में स्वीकार करें। आपके द्वारा मांगे जा रहे अन्य सामान, चाइनिंग का उपयोग करने के बारे में राय हैं, और उसके लिए कोई सही / गलत उत्तर नहीं है। यह वास्तव में आप पर निर्भर है। शायद आप छोटे विवरणों के बारे में बहुत अधिक चिंता कर रहे हैं?
रिएक्टगुलर

3

वे विधियाँ स्वयं के उदाहरण को संशोधित करती हैं।

भाषा के आधार पर, ऐसी विधियाँ हैं जो उनके उदाहरण या मापदंडों को लौटाती void/ unitसंशोधित करती हैं और गैर-मुहावरेदार होती हैं। यहां तक ​​कि उन भाषाओं में जो अधिक करते थे (C #, C ++), यह अधिक कार्यात्मक शैली प्रोग्रामिंग (अपरिवर्तनीय वस्तुओं, शुद्ध कार्यों) की ओर बदलाव के साथ फैशन से बाहर हो रहा है। लेकिन मान लेते हैं कि अब इसके लिए एक अच्छा कारण है।

क्या ऐसा करने का एकमात्र कारण यही होगा?

कुछ व्यवहारों के लिए (सोचें x++) यह उम्मीद की जाती है कि ऑपरेशन परिणाम लौटाता है, भले ही यह चर को संशोधित करता हो। लेकिन यह मोटे तौर पर केवल अपने दम पर करने का कारण है।

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

निर्भर करता है।

उन भाषाओं में जहां कॉपी / नई और वापसी आम है (C # LINQ और स्ट्रिंग्स) तो उसी संदर्भ को वापस करना भ्रामक होगा। उन भाषाओं में जहां संशोधन और वापसी आम है (कुछ C ++ लाइब्रेरी) तो नकल करना भ्रामक होगा।

हस्ताक्षर को अस्पष्ट बनाना (लौटकर voidया गुणों की तरह भाषा निर्माणों का उपयोग करके) स्पष्ट करने का सबसे अच्छा तरीका होगा। उसके बाद, नाम को यह स्पष्ट करना पसंद SetFooहै कि आप मौजूदा उदाहरण को संशोधित कर रहे हैं अच्छा है। लेकिन कुंजी उस भाषा / पुस्तकालय के मुहावरों को बनाए रखना है, जिसके साथ आप काम कर रहे हैं।


आपके उत्तर के लिए Thx। मैं मुख्य रूप से .NET फ्रेमवर्क के साथ काम कर रहा हूं, और आपके जवाब से यह गैर-मुहावरेदार चीजों से भरा है। जबकि LINQ मेथड्स जैसी चीजें ऑपरेशंस आदि को लागू करने के बाद मूल की एक नई कॉपी लौटाती हैं, Clear()या Add()किसी भी प्रकार के संग्रह जैसी चीजें उसी उदाहरण और रिटर्न को संशोधित करेंगी void। दोनों मामलों में आप कहते हैं कि यह भ्रामक होगा ...
मार्टिन ब्रौन

@modix - परिचालनों को संलग्न करते समय LINQ एक प्रति वापस नहीं करता है ।
तेलस्टीन

obj = myCollection.Where(x => x.MyProperty > 0).OrderBy(x => x.MyProperty);फिर मैं क्यों कर सकता हूं ? Where()एक नया संग्रह वस्तु देता है। OrderBy()यहां तक ​​कि एक अलग संग्रह वस्तु देता है, क्योंकि सामग्री का आदेश दिया गया है।
मार्टिन ब्रॉन

1
@modix - वे नई वस्तुओं है कि लागू वापसी IEnumerable, लेकिन स्पष्ट होना, वे प्रतियां नहीं हैं, और वे नहीं संग्रह (के अलावा हैं ToList, ToArray, आदि)।
तेलस्टीन

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

0

(मैंने C ++ को आपकी प्रोग्रामिंग-भाषा माना)

मेरे लिए यह ज्यादातर पठनीयता का पहलू है। यदि A, B, C संशोधक हैं, खासकर यदि यह एक अस्थायी ऑब्जेक्ट है जो किसी फ़ंक्शन के पैरामीटर के रूप में पारित किया जाता है, जैसे

do_something(
      CPerson('name').age(24).height(160).weight(70)
      );

की तुलना में

{
   CPerson person('name');
   person.set_age(24);
   person.set_height(160);
   person.set_weight(70);
   do_something(person);
}

अगर यह ठीक है कि संशोधित उदाहरण के संदर्भ में वापस लौटना है, तो मैं हाँ कहूंगा, और आपको उदाहरण के लिए धारा ऑपरेटरों '>>' और '<<' ( http://www.cprogramming.com/tutorial/ operator_overloading.html )


1
आपने गलत माना, यह C # है। हालाँकि मैं चाहता हूं कि मेरा प्रश्न अधिक सामान्य हो।
मार्टिन ब्रॉन

यकीन है, जावा भी हो सकता था, लेकिन यह एक मामूली बात थी, बस मेरे उदाहरण को संचालकों के संदर्भ में रखना। सार यह था कि यह पठनीयता के लिए उबलता है, जो पाठक की अपेक्षाओं और पृष्ठभूमि से प्रभावित होता है, जो स्वयं विशेष भाषा / रूपरेखा में सामान्य प्रथाओं से प्रभावित होते हैं - जिनके साथ एक व्यवहार कर रहा है - जैसा कि अन्य उत्तरों ने भी बताया है।
एड्रियन

0

आप संशोधित वापसी के बजाय कॉपी वापसी के साथ विधि का चयन भी कर सकते हैं।

एक अच्छा C # उदाहरण स्ट्रिंग है। (a, b) जो स्ट्रिंग को परिवर्तित नहीं करता है जिस पर इसे लागू किया गया था लेकिन इसके बजाय एक नया स्ट्रिंग लौटाता है जिससे आप आसानी से श्रृंखला से दूर जा सकते हैं।


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

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