Instof जावा के लिए प्रतिस्थापन?


10

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

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

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

क्या ऐसा करने का एक बेहतर तरीका है या क्या मैं instanceofवस्तुओं के विशिष्ट क्षेत्रों को प्राप्त करने के लिए किसी प्रकार के प्रतिबिंब का उपयोग कर रहा हूं ?


10
ऐसा नहीं है कि कीवर्ड instanceofगलत है; किसी वस्तु के वर्ग को खोजने की कोशिश करना आमतौर पर समस्या है। हमेशा गलत नहीं, लेकिन शायद आपके मामले में ऐसा है। हो सकता है कि यदि आप हमें बताएं कि आप क्या हासिल करना चाहते हैं, तो हम बहुरूपता का उपयोग करके समाधान सुझा सकते हैं।
एंड्रेस एफ।

2
ठीक है, प्रत्येक वर्ग के पास इसके लिए विशिष्ट डेटा है। मैं इनमें से विशिष्ट डेटा को खींचना चाहता हूं। मुझे लगता है कि मुझे मेरे पास मौजूद मदद का जवाब मिल गया है। एक विधि जैसा कुछ कहा जाता getSpecifics()है, जो प्रत्येक पर अलग-अलग लागू होता है, प्रत्येक में कक्षा के लिए विशिष्ट डेटा लौटता है?
थॉमस मिशेल

जवाबों:


16

कारण instanceofहतोत्साहित किया जाता है कि यह OOP नहीं है।

किसी वस्तु के कॉलर / उपयोगकर्ता के पास यह जानने का कोई कारण नहीं होना चाहिए कि वह किस ठोस वर्ग से परे का उदाहरण है, जिस प्रकार के चर को वह घोषित करता है।

यदि आपको उपवर्गों में अलग-अलग व्यवहार की आवश्यकता है, तो एक विधि जोड़ें और उन्हें अलग तरीके से लागू करें।


1
तो getSpecifics()प्रत्येक वर्ग पर एक विधि (या कुछ समान) जो प्रत्येक वर्ग के लिए बारीकियों को वापस कर देगा। क्या यह सबसे अच्छा तरीका है?
थॉमस मिशेल

@Schmooo आपको वास्तव में यह सोचने की ज़रूरत है कि वर्ग वृक्ष के भीतर आम कार्यक्षमता कहाँ मौजूद है और प्रत्येक स्तर पर क्या अनुबंध मौजूद हैं।

3
लेकिन उस मामले के बारे में क्या जब आपकी वस्तु परतों को पार करती है और प्रकार की जानकारी खो जाती है? उदाहरण मैं बना List। मैं इसे किसी भी वस्तु पर ले जाता हूं Iterable। अब वह दूसरी वस्तु एक तीसरी वस्तु के पास है जो Listअनुकूलन के लिए या तो लेती है , Iterableलेकिन बहुत धीमी है। दूसरे को यह नहीं पता होना चाहिए कि इसकी एक सूची है, लेकिन तीसरा बहुत जानना चाहेंगे। तीसरा ऑब्जेक्ट नहीं देखना चाहिए कि क्या यह अनुकूलन लागू कर सकता है? उदाहरण के लिए अमरूद देखें FluentIterableजो ऐसा करता है।
लॉरेंट बोर्गुल्ट-रॉय

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

9

instanceof जरूरी नहीं कि बुरी चीज हो, लेकिन यह एक ऐसी चीज है जिस पर एक नजर डालनी चाहिए।

जहाँ यह सही ढंग से काम करता है इसका एक उदाहरण उस जगह पर है जहाँ किसी को आधार प्रकार का एक संग्रह मिलता है और आप केवल उप-प्रकार के लोगों को चाहते हैं। NetworkInterface.getNetworkInterfaces()रिटर्न से नेटवर्क एड्रेस प्राप्त करना नेटवर्कइंटरफेस ऑब्जेक्ट जिसमें InetAddress ऑब्जेक्ट का संग्रह है, जिनमें से कुछ Inet4Address हैं और कुछ Inet6Address हैं। यदि कोई Inet4Address ऑब्जेक्ट के लिए संग्रह को फ़िल्टर करना चाहता है, तो उसे Instof का उपयोग करना आवश्यक है।

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

जब आप एक बेस क्लास लौट रहे हैं, जब तक कि इस तरह से डिज़ाइन किए जाने का कोई अच्छा कारण न हो (पिछले संस्करण के विनिर्देशों के बीच पीछे की संगतता) आप अंतर्निहित प्रकारों को देखने की कोशिश नहीं कर रहे हैं। यदि आपको एक सेट लौटाया जाता है, तो आप जानते हैं कि आपको एक सेट मिल रहा है। यह डेवलपर को बाद में किसी भी विशिष्ट प्रकार (SortedSet) को वापस करने या कुछ भी तोड़ने के बिना अंतर्निहित प्रकार (HashSet to TreeSet) को बदलने की अनुमति देता है।

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


यह संभव है कि इंटरफ़ेस निर्दिष्ट करना एक isOfType(SomeEnum.IPv4)विधि हो सकता है कि इस तरह के गुणों के लिए फ़िल्टर करने का एक बेहतर तरीका हो सकता है जैसे कंक्रीट प्रकार का निरीक्षण करना instanceof। यदि आप अपने आईपीवी 4 कार्यान्वयन वर्ग को बाद में विभाजित करना चाहते हैं तो क्या होगा? ऐसा नहीं है कि यह हमेशा बेहतर होता है, लेकिन यह एक विचार है।
स्टीवन श्लैंस्कर

@StevenSchlansker उस विशिष्ट वर्ग के लिए काम कर सकता है। लेकिन क्या होगा अगर किसी को यह देखने के लिए ठोस प्रकार का निरीक्षण करने की आवश्यकता है कि क्या एक डाली संभव है (या सिर्फ एक डाली जाएगी और अपवाद को पकड़ेगी?) Inet6Address InetAddress की तुलना में अधिक विधियों को लागू करता है। इसके लिए इंटरफेस के साथ काम करना मुश्किल होगा (एक एंम जो पैकेज में हर वर्ग को शामिल करता है? या क्लास लोडर?) और इसका मतलब है कि विधि को हाथ से लागू किया जाना चाहिए (या ऑब्जेक्ट में कुछ प्रतिबिंब कोड)। विचार करें कि कैसे करना है (o instanceof Serializable) || (o instanceof Externalizable)

1

आप getClass () विधि का उपयोग कर सकते हैं।

क्या आप सुनिश्चित हैं कि आपको तीन अलग-अलग वर्गों की आवश्यकता है? शायद एक स्विच के साथ एक वर्ग बेहतर सेवा करेगा?


7
getClassऔर instanceofशेयर नीचे। जब यह फिट बैठता है, तो पॉलीमॉर्फिज्म दोनों से बेहतर होता है, और मैं इसे ओपी के उपयोग के मामले में नहीं देखता।

आपके पहले वाक्य के खिलाफ मेरे पास कुछ नहीं है। लेकिन दूसरा एक - क्षमा करें, मैं समझ नहीं सकता कि आप क्या मतलब है।
गंगनुस

1
साथ getClassमैं नहीं अभी भी का उपयोग कर के रूप में ही इस मुद्दे को साझा करते हैं instanceof? मुझे अभी भी पता लगाना होगा कि मेरे पास क्या है और फिर कार्यों का एक सेट कॉल करें। आदर्श रूप से मैं एक ऐसी विधि चाहता हूं, जो उस वस्तु के लिए आवश्यक डेटा को उस वर्ग के लिए वापस लौटा दे।
थॉमस मिशेल

मैं पॉलिमोर्फिज्म को नजरअंदाज करते हुए आपके बारे में शिकायत कर रहा हूं, क्योंकि यह अक्सर बेहतर विकल्प होता है। मुझे पूरा यकीन है कि प्रश्न में उपयोग का मामला बहुरूपता के साथ किया जा सकता है, इसलिए मुझे या तो उपयोग करने की आवश्यकता नहीं है। (इसके अलावा, किसी और के उत्तर को पुन: प्रस्तुत करना अच्छा नहीं है।)

2
@ गंगस मैं इसे "हमला" नहीं मानता, मेरा मतलब है कोई अपराध नहीं। जो कुछ भी लेकिन। नहीं, सवाल यह नहीं है कि "और क्या उपयोग किया जा सकता है", यह "ऐसा करने का एक बेहतर तरीका है"। जब तक आप बहस करना चाहते हैं, तब तक getClassयह एक बेहतर तरीका है, इसका कोई जवाब नहीं है। अधिकांश ;-)

1

आमतौर पर जब मैं अपने आप को किसी वस्तु के प्रकार को जानना चाहता हूं तो इसका मतलब है कि मैंने अपनी वस्तु संरचना को गलत तरीके से लागू किया है। ज्यादातर बार यह एलएसपी का उल्लंघन करने के लिए नीचे आता है ।

हालांकि कई बार मैं चाहता हूं कि मेरे पास डायनामिक डिस्पैच करने का एक तरीका है और बॉयलर प्लेट कोड और फ्यूचरप्रूफ मेरी ऑब्जेक्ट संरचना को सहेजने का एक टन है। C # फ्रेमवर्क की नई किस्तों में डायनामिक कीवर्ड प्रदान करता है लेकिन जहाँ तक मुझे पता है कि जावा में अभी भी कुछ समान नहीं है।

उस ने कहा, आम तौर पर वर्ग की तुलना की तुलना में आम तौर पर बेहतर होता है क्योंकि यह विरासत का ठीक से समर्थन करेगा। आप रिफ्लेक्सियन एपीआई से आइसएसिग्नबल और अन्य जैसे तरीकों का भी उपयोग कर सकते हैं। यदि आप डायनामिक डिस्पैच जैसी किसी चीज को लागू करना चाहते हैं तो इसे रिफ्लेक्शन एपीआई के माध्यम से किया जा सकता है, लेकिन सावधान रहें, यह धीमा होगा। सावधानी के साथ उपयोग करें, आदर्श रूप से यदि आप कर सकते हैं तो आपको अपने ऐप की ऑब्जेक्ट संरचना और desing को ठीक करना चाहिए।

उम्मीद है की यह मदद करेगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.