2012-11-21 16 views
8

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

private List<T> theList; 

public List<T> getList() { 
    return Collections.unmodifiableList(theList); 
} 

हम सिर्फ स्वीकार करते हैं कि परिणाम एक List कि पूरी तरह से List इंटरफ़ेस को लागू नहीं करता है क्योंकि #add और दोस्तों UnsupportedOperationException फेंक है: जावा में मैं की तरह एक विधि जोड़ना होगा।

स्काला में, मैं iterator, size, और apply लेकिन कोई mutators (सूचकांक के आधार पर मानों पुन: प्राप्त करने के लिए) की तरह accessors साथ एक उचित विशेषता पाने की उम्मीद करेंगे। क्या ऐसा कोई प्रकार मौजूद है जो मुझे अभी तक नहीं मिला है?

+0

की तरह कुछ है '.toector' विधि जो आप चाहते हैं? यह 'वेरेक्टर' के रूप में 'ऐरेबफर' में मानों की प्रतिलिपि वापस कर देगा जो अपरिवर्तनीय है और तेज़ यादृच्छिक पहुंच का समर्थन करता है। ('.toVector' केवल 2.9.2 के लिए स्कैला 2.10 में है, आप 'वेक्टर() ++ myArrayBuffer' जैसे कुछ कर सकते हैं) – adelbertc

+0

संग्रह का आकार हजारों में हो सकता है। क्या यह अपरिवर्तनीय संग्रह प्रतिलिपि में मेरे विचलन को न्यायसंगत साबित करने के लिए पर्याप्त है? –

+0

आपका जावा उदाहरण एक अपरिवर्तनीय सूची नहीं बनाता है। यह सिर्फ एक immutabl-ish wrapper में एक mutable सूचियों को छुपाता है। अंतर्निहित सूची का संदर्भ रखने वाला कोई भी वस्तु अभी भी इसे बदल सकता है ... यदि यह आपके लिए पर्याप्त है, तो आप आसानी से एक ही दृष्टिकोण को कार्यान्वित कर सकते हैं ... – paradigmatic

उत्तर

9

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

तो आप स्केल में एक परिवर्तनीय बफर से दृश्य के रूप में अपरिवर्तनीय जैसे संग्रह नहीं प्राप्त कर सकते हैं क्योंकि यह गारंटी को तोड़ देता है।

लेकिन तुम तो जैसे आसान पर्याप्त unmodifiable परिवर्तनशील Seq की अवधारणा को लागू कर सकते हैं:

class UnmodifiableSeq[A](buffer: mutable.Seq[A]) extends mutable.Seq[A]{ 
    def update(idx: Int, elem: A) {throw new UnsupportedOperationException()} 

    def length = buffer.length 

    def apply(idx: Int) = buffer(idx) 

    def iterator = buffer.iterator 
} 

उपयोग:

val xs = Array(1, 2, 3, 4) 
val view = new UnmodifiableSeq(xs) 
println(view(2)) >> 3 
view(2) = 10 >> Exception in thread "main" java.lang.UnsupportedOperationException 

संपादित करें:

एक एक प्राप्त करने की शायद बेहतर तरीका संग्रह का अपरिवर्तनीय दृश्य collection.Seq पर डाउनकास्टिंग द्वारा किया गया है जो कोई परिवर्तनीय अद्यतन संचालन प्रदान नहीं करता है:

val xs = Array(1, 2, 3) 
val view: Seq[Int] = xs //this is unmodifiable 

या एक आवरण जो Seq फैली यदि आप अपने स्वयं के कस्टम परिवर्तनशील वर्ग है निर्माण।

class UnmodifiableView[A](col: MutableCollection[A]) extends collection.Seq[A]{ 
    def length = col.length 

    def apply(idx: Int) = col(idx) 

    def iterator = col.iterator 
} 

scala.collection.Seq विशेषता अचल स्थिति के किसी भी गारंटी नहीं है, लेकिन तो यह सही फिट लगता है यह भी किसी भी संशोधित संचालन की अनुमति नहीं है।

+1

मैं मानता हूं कि अपरिवर्तनीयता की अपरिवर्तनीय गारंटी को तोड़ना गलत होगा। लेकिन, क्या यह mutable.Seq # अद्यतन (Int, A) के अनुबंध को तोड़ने का भी बुरा विचार नहीं है? –

+1

@ क्रिस्टोफर मार्टिन - हाँ, मैं सहमत हूं। मुझे कबूल करना होगा कि मैंने अपने जवाब में गलती की है क्योंकि मुझे लगता है कि संग्रह। एसक्यू संग्रह के लिए उपनाम है। Immutable.Seq। जैसा कि यह पता चला है, यह नहीं है। तो आप संग्रह का विस्तार कर सकते हैं। सेक जो अपरिवर्तनीयता की गारंटी प्रदान नहीं करता है। मैं अपने जवाब में फिक्स जोड़ दूंगा। –

+0

यह सही है, धन्यवाद। मैंने यह भी उम्मीद नहीं की थी कि वहां तीन सेक लक्षण मौजूद होंगे (संग्रह, संग्रह। असंभव, संग्रह। Mutable)। अभी भी थोड़ा निराशाजनक है कि स्कैला में पहले से ही रैपर वर्ग नहीं है। मुझे लगता है कि मैं सिर्फ संग्रह में डाल दूंगा। ठीक है और दुर्व्यवहार की संभावना के बारे में इतना भयावह होना बंद करो। –

2

अपने बफर को Seq पर परिवर्तित करें, या scala.collection पैकेज का हिस्सा हैं जो अन्य अपरिवर्तनीय संग्रहों में से एक को कनवर्ट करें।

myBuffer.toSeq 
+0

अच्छा (शायद पर्याप्त पर्याप्त) सुझाव - लेकिन यह वास्तव में लौटाए गए मूल्य की असमानता सुनिश्चित नहीं करता है। वास्तव में गूंगा सहकर्मी सिर्फ सेक को एरेबफर में वापस ला सकता है और इसमें बदलाव कर सकता है। –

+2

नहीं, वह –

+2

नहीं कर सका, मैंने अभी कोशिश की है, और यह काम करता है ... स्कैला> आयात संग्रह। Mutable.ArrayBuffer; वैल ए = नया ऐरेबफर [Int]; a.append (1); वैल बी: सेक [Int] = a.toSeq; । B.asInstanceOf [ArrayBuffer [इंट]] संलग्न (2); –

0

यदि myBuffer.toSeq पर्याप्त नहीं है, तो आप अपनी खुद की कक्षा scala.collection.IndexedSeqOptimized को अंतर्निहित संग्रह में कॉल का प्रतिनिधित्व कर सकते हैं।

1

यदि आप चाहते हैं करने के लिए:

  • उपयोग केवल मौजूदा पुस्तकालय कार्यों (अपने स्वयं के आवरण नहीं लिख)
  • कॉपी करने के लिए सुनिश्चित करें से बचने के लिए सुनिश्चित करें कि दिए गए मान कुछ में ढाला नहीं जा सकता है परिवर्तनीय तो एक संभावना बस एक इटरेटर

    def getStuff = array.iterator 
    
वापस जाने के लिए है 0

यह वह जगह है एक विकल्प नहीं है, ज़ाहिर है, आपके विनिर्देशन विशेष रूप से एक Seq वापस जाने के लिए की आवश्यकता है, लेकिन यह

  • फोन करने वाले इस पर पुनरावृति करने के लिए के रूप में के लिए Seq के (for (x <- obj.getStuff))
  • ही सिंटैक्स का उपयोग की अनुमति देता है
  • कॉलर को obj.getStuff.toSeq या obj.getStuff.toList का उपयोग करके आसानी से एक सेक या सूची में कनवर्ट करने की अनुमति देता है।

(ध्यान दें कि .iterator के प्रलेखन स्पष्ट रूप से नहीं कहा गया है कि लौटे वस्तु कुछ परिवर्तनीय में ढाला नहीं जा सकता है, लेकिन ArrayBuffer.iterator का वर्तमान क्रियान्वयन वास्तव में एक unmodifiable iterator देता है।)

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