2009-08-27 21 views
15

मैं एक स्ट्रिंग के लिए किसी भी प्रकार से एक अंतर्निहित रूपांतरण (जैसे कि, इंट) बनाने के लिए कोशिश कर रहा हूँ में निहित डीईएफ़ अस्पष्टता से बचना ...स्काला

स्ट्रिंग के लिए एक अंतर्निहित रूपांतरण का मतलब RichString विधियों (रिवर्स) की तरह उपलब्ध नहीं हैं ।

implicit def intToString(i: Int) = String.valueOf(i) 
100.toCharArray // => Array[Char] = Array(1, 0, 0) 
100.reverse // => error: value reverse is not a member of Int 
100.length // => 3 

RichString के लिए एक अंतर्निहित रूपांतरण का मतलब स्ट्रिंग तरीकों (toCharArray की तरह) उपलब्ध

implicit def intToRichString(i: Int) = new RichString(String.valueOf(i)) 
100.reverse // => "001" 
100.toCharArray // => error: value toCharArray is not a member of Int 
100.length // => 3 

नहीं हैं दोनों अंतर्निहित रूपांतरण का उपयोग डुप्लिकेट किए गए तरीकों का मतलब है (लंबाई) की तरह अस्पष्ट हैं।

implicit def intToString(i: Int) = String.valueOf(i) 
implicit def intToRichString(i: Int) = new RichString(String.valueOf(i)) 
100.toCharArray // => Array[Char] = Array(1, 0, 0) 
100.reverse // => "001" 
100.length // => both method intToString in object $iw of type 
    // (Int)java.lang.String and method intToRichString in object 
    // $iw of type (Int)scala.runtime.RichString are possible 
    // conversion functions from Int to ?{val length: ?} 

इसलिए, यह परोक्ष स्ट्रिंग में बदलने के लिए और अभी भी सभी स्ट्रिंग और RichString तरीकों का समर्थन संभव है?

उत्तर

2

या तो एक बहुत बड़ा प्रॉक्सी वर्ग बनाने, या यह चूसना अप और यह स्पष्ट करने के लिए ग्राहक की आवश्यकता होती है: .length

+0

ऐसा लगता है कि 'इसे चूसना' सबसे अच्छा विकल्प है। स्काला में एपीआई डिज़ाइन एपीआई उपभोक्ता होने की तुलना में काफी कठिन है। मैं एक डेटाटाइप बनाना चाहता था जो एक मूल्य लपेटता है और एपीआई उपयोगकर्ता डेटाटाइप का इलाज करने की अनुमति देता है जैसे कि यह इंटर्न वाले मूल्य का प्रकार था। जैसे यदि यह एक इंट लपेटता है, तो वस्तु को एक int की तरह व्यवहार करें। बाहर निकलना यह बहुत मुश्किल है। मैं अपने डेटा-प्रकार सहायक तरीकों देने पर विचार कर रहा हूँ: प्रकार टी वैल internedValue: टी डीईएफ़ एस = internedValue.asInstanceOf [स्ट्रिंग] डीईएफ़ i = internedValue.asInstanceOf [इंट] ... आदि – Synesso

+20

पसंद करते हैं '(100: स्ट्रिंग)। लम्बाई, क्योंकि यह टाइप-सुरक्षित है, जबकि 'asInstanceOf' नहीं है। इसके अलावा, यह सुंदर और छोटा है। –

+2

न केवल वह, लेकिन जैसा कि इंस्टेंसऑफ कभी यहां काम नहीं करेगा, क्योंकि यह केवल डाउनकास्टिंग (जो यहां असफल होने के लिए बाध्य है) है और किसी भी अंतर्निहित रूपांतरण को बंद नहीं करेगा। दूसरे शब्दों में '100.asInstanceOf [स्ट्रिंग]। लम्बाई हमेशा 'क्लासकास्टएक्सप्शन' –

2

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

+0

यह एक उचित दृष्टिकोण की तरह लगता है, लेकिन बहुत सारे काम। इसके अलावा मुझे संदेह है कि यह भविष्य का सबूत नहीं है, क्योंकि अन्य निहित रूपांतरण पेश किए गए हैं। – Synesso

+0

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

+0

@ किम स्टीबेल: 'निश्चित रूप से यह बहुत काम है, लेकिन बहुत सी सोच नहीं है, सिर्फ टाइपिंग' प्रोग्रामर आलसी विचारक हैं, कड़ी मेहनत करने वाले टाइपिस्ट नहीं हैं। –

1

मैं उलझन में हूं: क्या आप किसी भी प्रकार से .toString का उपयोग नहीं कर सकते हैं, इस प्रकार निहित रूपांतरणों की आवश्यकता से बचें?

+0

मुझे नहीं लगता कि यह मामूली सूचक अपवादों को छोड़कर मामलों को बदल देगा। स्पष्ट होने के लिए, आप i.toString में String.valueOf (i) को बदलने का प्रस्ताव दे रहे हैं? – Synesso

5

100.asInstanceOf [स्ट्रिंग] मैं एक समाधान नहीं है, लेकिन टिप्पणी करेंगे RichString आपके intToString के बाद विधियां उपलब्ध नहीं हैं, यह स्पष्ट है कि स्कैला श्रृंखला निहित कॉल नहीं करता है (स्केल में प्रोग्रामिंग में 21.2 "प्रत्यारोपण के नियम" देखें)।

यदि आप इंटरमीडिएट String पेश करते हैं, तो स्कैला RichString पर अंतर्निहित अभिसरण करेगा (यह अनुमान Predef.scala में परिभाषित किया गया है)।

जैसे,

$ scala 
Welcome to Scala version 2.7.5.final [...]. 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> implicit def intToString(i: Int) = String.valueOf(i) 
intToString: (Int)java.lang.String 

scala> val i = 100 
i: Int = 100 

scala> val s: String = i 
s: String = 100 

scala> s.reverse 
res1: scala.runtime.RichString = 001 
+0

के साथ असफल रहेगा यह जानना अच्छा है! धन्यवाद। – Synesso

+0

क्या यह "केवल" परिपत्र अंतर्निहित परिवर्तनीय संबंधों की अनुमति देने की कमी है, या अन्य कारण हैं? चूंकि आपके पास सर्कल है, फिर भी आपको "निकटतम" कार्यान्वयन को खोजने में सक्षम होना चाहिए। ग्राफ को दो बार बिना ग्राफ के एक्सप्लोर करना मुश्किल नहीं है, हालांकि इसमें कुछ समय लग सकता है। – Raphael

5

स्काला 2.8 के रूप में, यह सुधार किया गया है। this paper के अनुसार (§ अस्पष्टता बचना):

इससे पहले, सबसे विशिष्ट ग अतिभारित विधि या अस्पष्ट रूपांतरण केवल विधि के तर्क प्रकार के आधार पर चुना जाना होगा। अतिरिक्त खंड था जिसमें कहा गया था कि सबसे विशिष्ट विकल्प अन्य विकल्पों के उचित सुपरक्लास में डिफाईड नहीं हो सकता है। यह योजना को निम्नलिखित के द्वारा स्कैला 2.8 में बदल दिया गया है, अधिक उदार एक: ओवरलोडेड विधि या अंतर्निहित के दो अलग-अलग लागू विकल्पों की तुलना करते समय, प्रत्येक विधि को विशिष्टता तर्क के लिए एक बिंदु मिलता है, और इसके लिए एक और बिंदु एक उचित उपclass में defeded जा रहा है। एक वैकल्पिक विकल्प "जीतता है" अगर इन दो तुलनाओं में अंकों की संख्या अधिक हो जाती है।इसका मतलब यह है कि यदि विकल्पों में समान तर्क प्रकार हैं, तो सबक्लास जीतने वाला एक है।

उदाहरण के लिए that other paper (§6.5) देखें।

+0

पहले पेपर का आपका लिंक टूटा हुआ है। –

2

स्वीकार किए गए समाधान (मिच ब्लेविन्स द्वारा पोस्ट किया गया) कभी काम नहीं करेगा: StringasInstanceOf का उपयोग करके डाउनकास्टिंग हमेशा विफल रहेगा।

implicit def stringLikeToRichString[T](x: T)(implicit conv: T => String) = new collection.immutable.StringOps(conv(x)) 

फिर अपने रूपांतरण (ओं) को परिभाषित: आपकी समस्या का

एक समाधान यह है कि (StringOps के रूप में यह अब नाम पर है या बल्कि,) RichString के लिए किसी भी स्ट्रिंग-परिवर्तनीय प्रकार से जोड़ने के लिए है पहले की तरह स्ट्रिंग:

scala> implicit def intToString(i: Int) = String.valueOf(i) 
warning: there was one feature warning; re-run with -feature for details 
intToString: (i: Int)String 

scala> 100.toCharArray 
res0: Array[Char] = Array(1, 0, 0) 

scala> 100.reverse 
res1: String = 001 

scala> 100.length 
res2: Int = 3