2015-07-01 9 views
9

मैं बस सोच रहा था कि क्यों java.util.Scannerjava.util.Iterator लागू करता है?स्कैनर इटरेटर <String> क्यों लागू करता है?

Scannerremove विधि लागू करता है और UnsupportedOperationException फेंकता है।

लेकिन इंटरफ़ेस को कार्यान्वित करते समय कक्षा नहीं होनी चाहिए, इंटरफ़ेस का अनुबंध पूरा करें?

iterator को लागू करने और अपवाद को फेंकने वाली विधि जोड़ने का क्या उपयोग है?

क्यों न केवल इंटरफ़ेस के कार्यान्वयन से बचें और इसे सरल रखें?

यह तर्क कर सकते हैं कि यह परिभाषित किया गया है ताकि वर्ग जो Scanner का विस्तार हो सकता है विधि को लागू कर सकता है, AbstractList की तरह एक add विधि है कि एक UnsupportedOperationException फेंकता है। लेकिन AbstractList एक abstract वर्ग है, जबकि Scanner एक final कक्षा है।

क्या यह एक खराब डिजाइन अभ्यास नहीं है?

+0

एक संबंधित [प्रश्न] (http://stackoverflow.com/questions/22050848/do-collections-unmodifiablexxx-methods-violate-lsp) इसके बारे में आपके संदेह के बारे में 'असमर्थितऑपरेशन अपवाद' फेंकने के बारे में। चूंकि लोगों ने 'निकालना' की ओर इशारा किया है एक वैकल्पिक विधि है जिसे ठोस वर्ग द्वारा लागू नहीं किया जा सकता है। तो यह दस्तावेज़ीकरण का उल्लंघन नहीं कर रहा है। लेकिन एक सिद्धांत लिस्कोव प्रतिस्थापन सिद्धांत है जिसे मैंने महसूस किया कि यह उल्लंघन कर रहा है। लेकिन मुझे यकीन नहीं है .. मैंने जो प्रश्न पूछा है, उसे पढ़ें। –

+0

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

+3

हां, जावा संग्रह पुस्तकालय खराब डिजाइन किया गया था। केवल पढ़ने-योग्य इटरेटर इंटरफ़ेस होना चाहिए था, लेकिन ऐसा नहीं है। –

उत्तर

6

मैं कहेंगे हाँ, Iterator एक डिजाइन दोष है, और एक अपरिवर्तनीय Collection कार्यान्वयन बनाने के प्रयास के रूप में एक ही श्रेणी में फेंक।

यह Interface Segregation Principle का उल्लंघन करती है और डेवलपर्स के लिए मजबूर करता JavaDocs (कुख्यात UnsupportedOperationException) में एक corner case शामिल करने के लिए Liskov Subsitution Principle उल्लंघन से बचने के। आपको यह Collection#remove विधियों में भी मिल जाएगा।

मेरा मानना ​​है कि डिजाइन इंटरफेस सड़ते हुए, एक नया (अपरिवर्तनीय) इंटरफेस में hasNext() और next() अलग-अलग रखने और (परिवर्तनशील) Iterator इंटरफेस की अनुमति से सुधार किया जा सकता है कि यह से निकाले जाते हैं:

interface Traversable<E> { 
    boolean hasNext(); 
    E next(); 
} 

interface Iterator<E> extends Traversable<E> { 
    void remove(); 
} 

final class Scanner implements Traversable<String> { 

} 

बेहतर नाम निश्चित रूप से हो सकता है उपयोग किया गया। मेरे खराब नामकरण विकल्पों के कारण कृपया इस पोस्ट को न करें।

Scanner क्यों पहले स्थान पर Iterator लागू करता है?

Scanner संग्रह को पार करने की भावना में एक पुनरावर्तक नहीं है। लेकिन Scanner का विचार "स्कैन" होने के लिए इनपुट की आपूर्ति करना है, जो कि पर कुछ है (String में वर्ण)।

मैं देख सकता हूं कि क्यों ScannerIterator लागू करेगा (आप उपयोग के मामले के लिए पूछ रहे थे)। उदाहरण के लिए, अपने खुद के Iterable प्रकार बनाने के लिए आप चाहते थे कि अगर एक String को निर्दिष्ट परिसीमक से अधिक पुनरावृति करने के लिए:

class ScannerWrapper implements Iterable<E> { 
    public Scanner scanner; 

    public ScannerWrapper(Scanner scanner) { 
     this.scanner = scanner; 
    } 

    public Iterator<String> iterator() { 
     return scanner; 
    } 
} 

Scanner scanner = new Scanner("one,two,three"); 
scanner.useDelimiter(","); 
ScannerWrapper wrapper = new ScannerWrapper(scanner); 

for(String s : wrapper) { 
    System.out.println(s); 
} 

लेकिन यह होता भी है, तो JDK एक Traversable प्रकार का समर्थन किया और अनुमति बढ़ाया छोरों Traversable आइटम स्वीकार करने के लिए काम किया, चूंकि इस फैशन में संग्रह से निकालने से ConcurrentModificationException फेंक सकता है, जो इसके बजाए एक इटरेटर का उपयोग करता है।

निष्कर्ष

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

JDK, और अब इसे बदलने कोड तोड़ने में परिणाम होगा इस (जैसे कि एक ImmutableMap मैं उपर्युक्त में सरणियों और प्रयासों के लिए length उजागर के रूप में बुरा डिजाइन विकल्प,) की तरह सामान से भरा है।

+2

आपके उत्तर में इसमें बहुत स्पष्टता है। आपके विस्तृत स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। :) –

0

यह सिर्फ एक समर्थित विधि नहीं है। इसे लागू करने से बचने के लिए इस तरह एक हटाने के तरीके के बिना एक समान इंटरफ़ेस की आवश्यकता होगी। NotImplementedException फेंकने वाली विधि से बचने के लिए बस कई समान इंटरफेस बनाने के लिए यह अच्छा डिज़ाइन है?

Scanner का उपयोग करने वाले किसी भी व्यक्ति को पता है (या जल्द ही पता चलेगा कि remove() विधि का उपयोग नहीं किया जा सकता है, इसलिए इसका वास्तव में कोई व्यावहारिक प्रभाव नहीं है। यह नो-ऑप भी हो सकता है, क्योंकि प्रभावी रूप से आइटम हटा दिया गया है, बस remove() के कारण नहीं, लेकिन यह शायद अपवाद फेंकने के लिए स्पष्ट है।

+0

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

+0

यह बिल्कुल बेहतर डिजाइन नहीं है। मैं मानक लाइब्रेरी में 'Iterable',' IterableWithoutRemove' और 'IterableWithoutAdd' इंटरफेस नहीं करना चाहता, सिर्फ इसलिए कि आपको यह पसंद नहीं है कि कोई विधि 'NotImplementedException' को फेंकता नहीं है। उल्लेख नहीं है कि कई 'Iterable' इंटरफेस के अलावा,' Iterator' इंटरफेस भी तीन गुना होगा। अनावश्यक अव्यवस्था जोड़ना अच्छा डिजाइन नहीं है। – Kayaman

+0

+1 त्वरित प्रतिक्रिया के लिए धन्यवाद और मुझे समझ में आता है। मैं पूरी तरह से सहमत हूं, एक मानक पुस्तकालय को अवांछित जटिलता के साथ भरना नहीं चाहिए। लेकिन फिर स्कैनर इटरेटर लागू करने के द्वारा क्या अच्छा बनाया जाता है। इटरेटर के बिना अकेले क्यों खड़े हो सकते हैं? बीटीडब्ल्यू 'IterablewithoutAdd' .. गंभीरता से ?? : पी –

3

क्योंकि इटरेटर को कार्यान्वित करने से स्कैनर का उपयोग किया जा सकता है, जहां कहीं भी पढ़ा जा सकता है केवल इटरेटर का उपयोग किया जा सकता है।

इसके अलावा यह अनुबंध लागू करता है। इटरेटर प्रलेखन से (जोर मेरा):

निकालें() अंतर्निहित संग्रह से पिछले तत्व इस इटरेटर (वैकल्पिक आपरेशन) द्वारा दिया निकालता है।

+1

प्रत्येक लूप के लिए स्कैनर का उपयोग नहीं किया जा सकता क्योंकि यह इटरेटर लागू करता है और इटेबल नहीं है। –

+0

@ नरेंद्रपाथाई संस्कार है .. हालांकि आपके द्वारा दिए गए उदाहरण गलत हैं, फिर भी मैं समझता हूं कि केवल पढ़ने के लिए पुनरावृत्ति ऑपरेशन के स्थान पर हम इसका उपयोग कर सकते हैं। लेकिन क्या ऐसी स्थिति है? –

+0

ओह, तर्क, सही! खराब उदाहरण। –

0

एक आधिकारिक उत्तर के लिए, Collections Framework Overview देखें। डिज़ाइन लक्ष्य के लिए नीचे तक स्क्रॉल करें।

कोर इंटरफेस की संख्या कम रखने के लिए, इंटरफेस अस्थिरता, परिवर्तनीयता, और resizability के रूप में इस तरह के सूक्ष्म भेद पर कब्जा करने के प्रयास न करें। इसके बजाए, कोर इंटरफेस में कुछ कॉल वैकल्पिक हैं, UnsupportedOperationException को फेंकने के लिए कार्यान्वयन को सक्षम करने के लिए यह इंगित करने के लिए कि वे निर्दिष्ट वैकल्पिक ऑपरेशन का समर्थन नहीं करते हैं। संग्रह कार्यान्वयनकर्ताओं को स्पष्ट रूप से दस्तावेज़ होना चाहिए जो वैकल्पिक संचालन को कार्यान्वयन द्वारा समर्थित किया जाता है।

जैसा कि पिछले उत्तरों ने इंगित किया है, संग्रह ढांचा कई इंटरफेस में अपने इंटरफेस को विघटित करके लिस्कोव सबस्टिशन को रोक सकता है। ढांचे में कोर इंटरफेस की संख्या को कम करने के लिए, उस दृष्टिकोण को माना और अस्वीकार कर दिया गया था।

+0

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

+0

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

संबंधित मुद्दे