2011-08-17 18 views
6

मैं स्कैला के अपरिवर्तनीय मानचित्र से प्राप्त करना चाहता हूं। यह इस तरह के रूप में परिभाषित किया जाता है:क्या स्कैला में बेस क्लास/विशेषता का अंतर बदलना संभव है?

trait Map[A, +B] 

दुर्भाग्य से, मेरी कार्यान्वयन बी में अपरिवर्तनीय मैं निम्नलिखित की कोशिश की होने की जरूरत है, लेकिन सफलता नहीं मिली:

def +(kv : (A, B)) : MyMap[A, B] = { ... } 

override def +[B1 >: B](kv : (A, B1)) : MyMap[A, B1] = 
    throw new IllegalArgumentException() 

शायद @uncheckedVariance साथ एक चाल है?

+1

शायद आप प्राप्त करने के बजाय सदस्य मानचित्र का उपयोग कर सकते हैं? – Owen

+0

इसके अलावा, इसे invariant क्यों होना चाहिए? मैंने सोचा था (हालांकि मुझे बहुत अधिक स्कैला नहीं पता) केवल एक बार जब आपको अचूकता की आवश्यकता होती है तो यह एक स्रोत और सिंक दोनों हो सकता है, लेकिन नक्शे अपरिवर्तनीय हैं, इसलिए यह एक सिंक नहीं हो सकता है। – Owen

+0

मैं एक द्वि-दिशात्मक मानचित्र लागू करना चाहता हूं। यदि मैं मानचित्र को कार्यान्वित करता हूं तो कोई बड़ा सौदा नहीं है, और केवल दो आंतरिक मानचित्रों को आगे भेजता है जो आगे और पिछड़े मैपिंग को परिभाषित करते हैं, लेकिन मुझे उस मामले में आविष्कार की आवश्यकता है। –

उत्तर

1

कॉन्वर्सिस से पूरी तरह से छुटकारा पाने के लिए निश्चित रूप से अस्वस्थ होगा, और इसकी अनुमति नहीं है। m: Map[A, String], और v : Any दिए गए, आप val mm : Map[A, Any] = m + v कर सकते हैं। यह Map परिभाषा कहता है, और सभी कार्यान्वयनियों का पालन करना चाहिए। आपकी कक्षा परिवर्तनीय हो सकती है, लेकिन इसे मानचित्र के पूर्ण कॉन्वर्स इंटरफेस को कार्यान्वित करना होगा।

अब त्रुटि को फेंकने के लिए + को फिर से परिभाषित करना एक अलग कहानी है (अभी तक बहुत अच्छी नहीं है)। आपके नए + विधि के साथ समस्या यह है कि जेनेरिक मिटाने के बाद, यह अन्य + विधि से समान हस्ताक्षर है। एक चाल है: अंतर्निहित पैरामीटर में जोड़ें, ताकि आपके हस्ताक्षर में दो पैरामीटर हों, जो इसे पहले से अलग करता है।

def +(kv : (A,B))(implicit useless: A <:< A) : MyMap[A,B] 

(यह वास्तव में बात नहीं क्या निहित पैरामीटर आप देख रहे हैं, जब तक कि एक पाया जाता है। implicit useless: Ordering[String] तरह ही काम करता है)

ऐसा करने से, आप अधिक भार के साथ सामान्य समस्या है । यदि आप ऐसा करने के लिए संकलक के बिना बी जोड़ते हैं, तो असफल विधि को बुलाया जाएगा। वहां एक प्रकार की जांच करने के लिए बेहतर हो सकता है ताकि बी इंस्टेंस स्वीकार किए जाएं। इसके लिए आपके मानचित्र में एक मैनिफेस्ट [बी] प्राप्त करने की आवश्यकता होगी।

3

समस्या यह है कि यदि आप एक अपरिवर्तनीय मानचित्र से एक परिवर्तनीय संस्करण प्राप्त करते हैं, तो आप प्रकार सुरक्षा को तोड़ देंगे। उदाहरण के लिए:

val dm = DiotMap(1 -> "abc") 
val m: Map[Int, Any] = dm 

यह घोषणा, वैध है क्योंकि Map covariant है। यदि आपका संग्रह कॉन्वर्सिस को संभाल नहीं सकता है, तो जब मैं m का उपयोग करता हूं तो क्या होगा?