मैं कहेंगे हाँ, 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
में वर्ण)।
मैं देख सकता हूं कि क्यों Scanner
Iterator
लागू करेगा (आप उपयोग के मामले के लिए पूछ रहे थे)। उदाहरण के लिए, अपने खुद के 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
उजागर के रूप में बुरा डिजाइन विकल्प,) की तरह सामान से भरा है।
एक संबंधित [प्रश्न] (http://stackoverflow.com/questions/22050848/do-collections-unmodifiablexxx-methods-violate-lsp) इसके बारे में आपके संदेह के बारे में 'असमर्थितऑपरेशन अपवाद' फेंकने के बारे में। चूंकि लोगों ने 'निकालना' की ओर इशारा किया है एक वैकल्पिक विधि है जिसे ठोस वर्ग द्वारा लागू नहीं किया जा सकता है। तो यह दस्तावेज़ीकरण का उल्लंघन नहीं कर रहा है। लेकिन एक सिद्धांत लिस्कोव प्रतिस्थापन सिद्धांत है जिसे मैंने महसूस किया कि यह उल्लंघन कर रहा है। लेकिन मुझे यकीन नहीं है .. मैंने जो प्रश्न पूछा है, उसे पढ़ें। –
मैंने आपका प्रश्न देखा और मेरा मानना है कि आप सही हैं। यह वास्तव में एलएसपी तोड़ रहा है।मुझे यह भी विश्वास है कि कक्षा को कभी भी इटरेटर इंटरफेस लागू नहीं करना चाहिए था। यदि आप एक पोस्ट कर सकते हैं तो मुझे आपका जवाब स्वीकार करने में खुशी होगी। –
हां, जावा संग्रह पुस्तकालय खराब डिजाइन किया गया था। केवल पढ़ने-योग्य इटरेटर इंटरफ़ेस होना चाहिए था, लेकिन ऐसा नहीं है। –