स्विच स्टेटमेंट को फिर से भरना और क्या स्विच स्टेटमेंट के लिए कोई वास्तविक उपयोग है?


28

मैं इस लेख को पढ़ रहा था और सोच रहा था कि क्या हम सभी स्विच स्टेटमेंट को डिक्शनरी या फ़ैक्टरी से बदल कर निकाल देंगे ताकि मेरे प्रोजेक्ट्स में बिल्कुल भी स्विच स्टेटमेंट न हों।

कुछ बहुत जोड़ नहीं था।

सवाल यह है कि क्या स्विच स्टेटमेंट का कोई वास्तविक उपयोग होता है या क्या हम आगे बढ़ते हैं और उन्हें एक शब्दकोश या एक फैक्ट्री विधि से प्रतिस्थापित करते हैं (निश्चित रूप से, फैक्टरी विधि का उपयोग करके, ऑब्जेक्ट बनाने के लिए स्विच स्टेटमेंट का न्यूनतम उपयोग होगा। कारखाने का उपयोग कर ... लेकिन वह इसके बारे में है)।


10
मान लें कि आप एक कारखाने को लागू करते हैं, तो आप कैसे तय करेंगे कि किस प्रकार की वस्तु का निर्माण करना है?
कोडार्ट

2
बहुत संबंधित: programmers.stackexchange.com/questions/146771/…
pdr

@ कोडकोड: मैं निश्चित रूप से, कहीं न कहीं स्थितियां तय करूंगा कि किस ठोस कार्यान्वयन का उपयोग करना है।
Kanini

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

जवाबों:


44

switchबयान और बहुरूपता दोनों का उपयोग है। ध्यान दें कि एक तीसरा विकल्प भी मौजूद है (उन भाषाओं में जो फ़ंक्शन पॉइंटर्स / लैम्ब्डा और उच्च-क्रम फ़ंक्शन का समर्थन करते हैं): हैंडलर फ़ंक्शन के लिए पहचानकर्ताओं को प्रश्न में मैप करना। यह उदा C में उपलब्ध है जो OO भाषा नहीं है, और C # जो कि * है, लेकिन जावा में (अभी तक) नहीं है जो OO भी है *।

कुछ प्रक्रियात्मक भाषाओं में (कोई बहुरूपता नहीं है और न ही उच्च-क्रम के कार्य) switch/ if-elseकथन समस्याओं के एक वर्ग को हल करने का एकमात्र तरीका थे। इसलिए कई डेवलपर्स, इस तरह से सोचने के आदी रहे, switchउन्होंने ओओ भाषाओं में भी उपयोग करना जारी रखा , जहां बहुदेववाद अक्सर एक बेहतर समाधान होता है। यही कारण है कि अक्सर switchबहुरूपता के पक्ष में बयानों से बचने / रिफ्लेक्टर करने की सिफारिश की जाती है।

किसी भी दर पर, सबसे अच्छा समाधान हमेशा मामला निर्भर है। सवाल यह है कि कौन सा विकल्प आपको लंबे समय में क्लीनर, अधिक संक्षिप्त, अधिक रखरखाव योग्य कोड देता है?

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

यदि एक ही switchकई स्थानों पर पॉप अप करना शुरू हो जाता है, तो इन सभी मामलों को एकजुट करने और कोड को सरल बनाने के लिए बहुरूपता शायद सबसे अच्छा विकल्प है। खासकर अगर भविष्य में और मामले जुड़ने की उम्मीद है; जितनी अधिक बार आपको हर बार अपडेट करने की आवश्यकता होगी, त्रुटियों के लिए उतनी अधिक संभावनाएं। हालाँकि, अक्सर व्यक्तिगत मामले संचालकों के लिए बहुत सरल होते हैं, या उनमें से बहुत सारे होते हैं, या वे इतने परस्पर जुड़े होते हैं, कि उन्हें एक पूर्ण बहुरूपी वर्ग पदानुक्रम में बदलकर ओवरकिल हो जाता है, या बहुत सारे डुप्लिकेट कोड और / या उलझा हुआ होता है, वर्ग पदानुक्रम बनाए रखने के लिए कठिन है। इस मामले में, इसके बजाय फ़ंक्शंस / लैम्ब्डा का उपयोग करना सरल हो सकता है (यदि आपकी भाषा आपको अनुमति देती है)।

हालाँकि, यदि आपके पास एक switchही जगह है, केवल कुछ मामलों में कुछ सरल करने के साथ, यह अच्छी तरह से इसे छोड़ने का सबसे अच्छा समाधान हो सकता है जैसा कि यह है।

* मैं "OO" शब्द का प्रयोग यहाँ करता हूँ; मुझे "वास्तविक" या "शुद्ध" OO क्या है, इस पर वैचारिक बहस में कोई दिलचस्पी नहीं है।


4
+1। इसके अलावा, उन सिफारिशों को शब्द दिया जाता है, " स्विच करने के लिए बहुरूपता पसंद करते हैं " और यह एक अच्छा शब्द विकल्प है, इस उत्तर को ध्यान में रखते हुए। यह स्वीकार करता है कि ऐसे हालात हैं जहां एक जिम्मेदार कोडर दूसरी पसंद बना सकता है।
कार्ल मैनस्टर

1
और ऐसे समय होते हैं जब आप स्विच दृष्टिकोण चाहते हैं, भले ही आपके कोड में उनमें से एक गजिलियन हो। मुझे एक कोड कोड मिला है जो 3 डी भूलभुलैया बनाता है। यदि कक्षा में एक-बाइट कक्षों को कक्षाओं के साथ बदल दिया गया था, तो मेमोरी का उपयोग अधिक हो जाएगा।
लोरेन Pechtel

14

यह वह जगह है जहां मैं एक डायनासोर होने के लिए वापस जाता हूं ...

स्विच स्टेटमेंट अपने आप में खराब नहीं हैं, इसका उपयोग जो कि उनमें से बना है जो कि समस्या है।

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

स्विच के रूप में शब्दकोश मुझे अधिक चुनौतीपूर्ण लगता है - मौलिक रूप से हाँ यदि आपका स्विच 100% मामलों को कवर करता है, लेकिन जहां आप डिफ़ॉल्ट होना चाहते हैं या कोई कार्रवाई के मामले नहीं हैं, तो यह थोड़ा और दिलचस्प होने लगता है।

मुझे लगता है कि इसकी पुनरावृत्ति से बचने का एक सवाल है और यह सुनिश्चित करने के लिए कि हम अपने ऑब्जेक्ट ग्राफ़ को सही स्थानों पर बना रहे हैं।

लेकिन समझ (स्थिरता) तर्क भी है और यह दोनों तरीकों में कटौती करता है - एक बार जब आप समझ जाते हैं कि यह सब कैसे काम करता है (पैटर्न और ऐप जिसमें इसे लागू किया गया है) तो यह आसान है ... लेकिन यदि आप कोड की एक पंक्ति में आते हैं जहां आप कुछ नया जोड़ने के लिए आपको फिर से काम करने / बदलने के लिए क्या करना है, यह जानने के लिए सभी जगह कूदना होगा।

उन सभी के लिए जो हमारे विकास के वातावरण में व्यापक रूप से सक्षम हैं मुझे अभी भी लगता है कि कोड को समझने में सक्षम होना वांछनीय है (जैसे कि यह थे) कागज पर प्रिंट आउट - क्या आप अपनी उंगली से कोड का पालन कर सकते हैं? मैं स्वीकार करता हूं कि वास्तव में नहीं, बहुत सारे अच्छे अभ्यास के साथ आज आप और अच्छे कारणों से नहीं कर सकते हैं, लेकिन इसका मतलब है कि कोड के साथ गति प्राप्त करना शुरू करना कठिन है (या शायद मैं अभी पुराना हूं ...)


4
मेरे पास एक शिक्षक था जिसने कहा कि आदर्श कोड को "लिखा जाना चाहिए ताकि कोई व्यक्ति जो प्रोग्रामिंग के बारे में कुछ नहीं जानता था (जैसे कि शायद आपकी माँ) उसे समझ सके।" दुर्भाग्य से यह एक आदर्श है, लेकिन शायद हमें अपनी माताओं को कोड समीक्षाओं में वैसे भी शामिल करना चाहिए!
माइकल के

+1 के लिए "लेकिन यदि आप कोड की एक एकल पंक्ति में आते हैं, जहाँ आपको कुछ नया जोड़ना है, तो आपको काम करने / बदलने के लिए क्या करना है, यह जानने के लिए सभी जगह पर कूदना होगा"
जल्दी से जल्दी

8

स्विच-स्टेटमेंट बनाम उप-प्रकार-बहुरूपता एक पुरानी समस्या है और अक्सर अभिव्यक्ति समस्या पर चर्चा में एफपी समुदाय में संदर्भित किया जाता है ।

मूल रूप से, हमारे पास प्रकार (कक्षाएं) और फ़ंक्शन (विधियां) हैं। हम सामान को कैसे कोडित करते हैं ताकि नए प्रकार या नए तरीकों को बाद में जोड़ना आसान हो?

यदि आप OO शैली में प्रोग्राम करते हैं, तो एक नई विधि जोड़ना मुश्किल है (क्योंकि इसका मतलब सभी मौजूदा कक्षाओं को फिर से भरना होगा), लेकिन नए वर्गों को जोड़ना बहुत आसान है जो पहले की तरह ही तरीकों का उपयोग करते हैं।

दूसरी ओर, यदि आप एक स्विच स्टेटमेंट (या इसके OO समतुल्य, ऑब्जर्वर पैटर्न) का उपयोग करते हैं तो नए कार्यों को जोड़ना बहुत आसान है लेकिन नए मामलों / वर्गों को जोड़ना कठिन है।

दोनों दिशाओं में इसकी अच्छी व्यापकता होना आसान नहीं है, इसलिए अपना कोड लिखते समय, यह निर्धारित करें कि क्या आप किस दिशा में आगे बढ़ने की संभावना रखते हैं, इस आधार पर बहुरूपता या स्विच स्टेटमेंट का उपयोग करें।


4
क्या हम एक शब्दकोश या एक कारखाने के साथ प्रतिस्थापित करके सभी स्विच स्टेटमेंट से छुटकारा पा लेते हैं ताकि मेरी परियोजनाओं में कोई भी स्विच स्टेटमेंट न हो।

नहीं, इस तरह के निरपेक्षता शायद ही कभी एक अच्छा विचार है।

कई जगह, शब्दकोश / लुकअप / फैक्ट्री / पॉलीमॉर्फिक प्रेषण एक स्विच स्टेटमेंट की तुलना में बेहतर डिज़ाइन प्रदान करेगा लेकिन आपको अभी भी शब्दकोश को पॉप्युलेट करना होगा। कुछ मामलों में, यह अस्पष्ट होगा कि वास्तव में क्या चल रहा है और बस इन-लाइन विवरण स्विच-इन अधिक पठनीय और रखरखाव योग्य है।


और वास्तव में, यदि आप कारखाने और शब्दकोश और लुकअप को अनियंत्रित करते हैं, तो यह मूल रूप से एक स्विच स्टेटमेंट बन जाएगा: यदि सरणी [हैश (खोज)] तो सरणी [हैश (खोज)] को कॉल करें। हालांकि यह रनटाइम-एक्सपेंडेबल होगा जो संकलित स्विच नहीं हैं।
ज़ैन लिंक्स

@ZanLynx, पूर्ण विपरीत सच है, कम से कम C # के साथ। यदि आप गैर-तुच्छ स्विच स्टेटमेंट के लिए उत्पादित IL को देखते हैं, तो आप देखेंगे कि कंपाइलर इसे डिक्शनरी में बदल देता है।
डेविड अरनो

@ दाविद अरनो: "पूर्ण विपरीत"? जिस तरह से मैंने इसे पढ़ा है हमने ठीक वैसी ही बात कही है। इसके विपरीत कैसे हो सकता है?
ज़ेन लिंक्स

2

यह देखना कि यह भाषा-अज्ञेय कैसे है, फॉल-थ्रू कोड switchबयानों के साथ सबसे अच्छा काम करता है :

switch(something) {
   case 1:
      foo();
   case 2:
      bar();
      baz();
      break;

   case 3:
      bang();
   default:
      bizzap();
      break;
}

बहुत अजीब डिफ़ॉल्ट मामले के साथ if, बराबर । और ध्यान रखें कि जितनी अधिक गिरावट आएगी, उतनी लंबी स्थिति सूची प्राप्त करेगी:

if (1 == something) {
   foo();
}
if (1 == something || 2 == something) {
   bar();
   baz();
}
if (3 == something) {
   bang();
}
if (1 != something && 2 != something) {
   bizzap();
}

(हालांकि, यह देखते हुए कि कुछ अन्य उत्तर क्या कहते हैं, मुझे लगता है कि मैं प्रश्न के बिंदु से चूक गया हूं ...)


मैं एक के switchरूप में एक ही स्तर पर होने के रूप में गिरावट के माध्यम से बयान के उपयोग का संबंध होगा goto। यदि किए जाने वाले एल्गोरिदम को नियंत्रण प्रवाह की आवश्यकता होती है जो कि संरचित प्रोग्रामिंग निर्माणों को फिट करता है, तो किसी को इस तरह के निर्माणों का उपयोग करना चाहिए, लेकिन यदि एल्गोरिथ्म ऐसे निर्माणों को फिट नहीं करता है, gotoतो अन्य नियंत्रण संरचनाओं को फिट करने के लिए झंडे या अन्य नियंत्रण तर्क को जोड़ने की कोशिश करने की तुलना में उपयोग करना बेहतर हो सकता है। ।
सुपरकाट

1

स्विच स्टेटमेंट के रूप में केस भेदभाव का वास्तविक उपयोग होता है। फ़ंक्शनल प्रोग्रामिंग लैंग्वेज कुछ ऐसे पैटर्न मैचिंग का उपयोग करती हैं जो आपको इनपुट के आधार पर फ़ंक्शन को अलग-अलग तरीके से परिभाषित करने की अनुमति देता है। हालाँकि ऑब्जेक्ट ओरिएंटेड भाषाओं में एक ही लक्ष्य को बहुरूपता का उपयोग करके अधिक सुरुचिपूर्ण ढंग से पहुँचा जा सकता है। आप बस विधि को कहते हैं और वस्तु के वास्तविक प्रकार के आधार पर, विधि के अनुरूप कार्यान्वयन को निष्पादित किया जाएगा। इस विचार के पीछे यही कारण है कि स्विच स्टेटमेंट एक कोड गंध है। हालाँकि, OO भाषाओं में भी, आप उन्हें अमूर्त कारखाने पैटर्न को लागू करने के लिए उपयोगी पा सकते हैं।

tl; dr - वे उपयोगी हैं, लेकिन अक्सर आप बेहतर कर सकते हैं।


2
मुझे वहां कुछ पूर्वाग्रहों की गंध आती है - क्यों पॉलीमॉर्फिज्म पैटर्न मिलान की तुलना में अधिक सुरुचिपूर्ण है? और आपको क्या लगता है कि एफपी में बहुरूपता मौजूद नहीं है?
तदमर्स

@tdammers सबसे पहले मेरा मतलब यह नहीं था कि एफपी में बहुरूपता मौजूद नहीं है। हास्केल तदर्थ और पैरामीट्रिक बहुरूपता का समर्थन करता है। पैटर्न मिलान एक बीजीय डेटाटाइप के लिए समझ में आता है। लेकिन बाहरी मॉड्यूल्स के लिए इसके लिए कंस्ट्रक्टर्स को एक्सपोज करना पड़ता है। स्पष्ट रूप से यह एक सार डेटा प्रकार (बीजीय डेटाटाइप्स के साथ एहसास) के इनकैप्सुलेशन को तोड़ता है। यही कारण है कि मुझे लगता है कि बहुरूपता एफपी में अधिक सुरुचिपूर्ण है (और संभव है)।
स्कारफ्रिज

आप टाइपकास्ट और उदाहरणों के माध्यम से बहुरूपता को भूल रहे हैं।
tdammers

क्या आपने कभी अभिव्यक्ति की समस्या के बारे में सुना है ? OO और FP अलग-अलग स्थितियों में बेहतर हैं, अगर आप इसके बारे में सोचना बंद कर दें।
हुगोमग

@tdammers आपको क्या लगता है कि जब मैं तदर्थ बहुरूपता का उल्लेख करता हूं तो मैं किस तरह की बात करता हूं? Hocell में Ad Hoc polymorphism का एहसास type classes के जरिए होता है। आप यह कैसे कह सकते हैं कि मैं इसे भूल गया? बस सच नहीं है।
स्कारफ्रिज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.