2009-09-10 7 views
23

मैं सोच रहा है कि क्या पारदर्शीimplicit रूपांतरण वास्तव में इस तरह के एक अच्छा विचार कर रहे हैं और क्या यह वास्तव में, implicits अधिक उपयोग करने के लिए उम बेहतर हो सकता है, स्पष्ट। उदाहरण के लिए, मान लीजिए मैं एक तरीका है जिसके एक Date एक पैरामीटर के रूप में स्वीकार करता है और मैं एक अंतर्निहित रूपांतरण जो बदल जाता है एक एक Date में String है:स्काला अंतर्निहित उपयोग विकल्पों

implicit def str2date(s: String) : Date = new SimpleDateFormat("yyyyMMdd").parse(s) 

private def foo(d: Date) 

तो जाहिर है मैं एक पारदर्शी implicit रूपांतरण के साथ इस फोन कर सकते हैं:

foo("20090910") 

क्या यह तथ्य बेहतर होगा कि मैं स्ट्रिंग को एक तारीख में अधिक स्पष्ट रूप से परिवर्तित कर रहा हूं?

class DateString(val s: String) { 
    def toDate : Date = new SimpleDateFormat("yyyyMMdd").parse(s) 
} 

implicit def str2datestr(s: String) : DateString = new DateString(s) 

तो फिर उपयोग लग रहा है और अधिक की तरह:

foo("20090910".toDate) 

इस का लाभ यह है कि यह बाद में क्या हो रहा है पर स्पष्ट है - मैं पारदर्शी implicit द्वारा अब कुछ समय के लिए बाहर पकड़ लिया गया है रूपांतरण मुझे (Option से Iterable किसी के बारे में पता होना चाहिए?) और यह उपयोग हमें अभी भी implicit एस की शक्ति का लाभ लेने की अनुमति देता है।

उत्तर

43

मेरा मानना ​​है कि निहित रूपांतरण करने का अधिक "स्पष्ट" तरीका कम से कम इस उदाहरण में पूरी तरह पारदर्शी की तुलना में पठनीयता के मामले में बेहतर है। जब आप हमेशा में सक्षम होने के लिए जब भी और प्रकार B की वस्तु की जरूरत है के रूप में प्रयोग की जाने वाली प्रकार A की एक वस्तु को देख सकते हैं

मेरी राय में, प्रकार A से पूरी तरह से पारदर्शी रूप से implicit s का उपयोग करके टाइप करने के लिए B ठीक है। उदाहरण के लिए, String के RandomAccessSeq[Char] पर अंतर्निहित रूपांतरण हमेशा समझ में आता है - String हमेशा, अवधारणात्मक रूप से, अक्षरों के अनुक्रम के रूप में देखा जा सकता है (सी में, एक स्ट्रिंग केवल वर्णों का क्रम है, उदाहरण के लिए)। x.foreach(println) पर कॉल सभीString एस के लिए समझ में आता है।

दूसरी ओर, अधिक स्पष्ट रूपांतरण प्रकार A का एक उद्देश्य कभी कभी प्रकार B की वस्तु के रूप में इस्तेमाल किया जा सकता है जब इस्तेमाल किया जाना चाहिए। आपके उदाहरण में, foo("bar") पर एक कॉल समझ में नहीं आता है और एक त्रुटि फेंकता है। चूंकि स्कैला ने अपवादों की जांच नहीं की है, foo(s.toDate) पर एक कॉल स्पष्ट रूप से संकेत देता है कि एक अपवाद फेंक दिया जा सकता है (s मान्य दिनांक नहीं हो सकता है)। इसके अलावा, foo("bar".toDate) स्पष्ट रूप से गलत दिखता है, जबकि आपको यह देखने के लिए प्रलेखन परामर्श करने की आवश्यकता है कि foo("bar") गलत क्यों हो सकता है। स्काला मानक पुस्तकालय में इस का एक उदाहरण String रों Int को रों से रूपांतरण, (String रों Int रों रूप में देखा जा सकता है, लेकिन नहीं हर समय) है RichString आवरण की toInt विधि के माध्यम से।

13

जब आप एक्स से वाई (जैसे स्ट्रिंग से लेकर दिनांक तक रूपांतरण के रूप में) में एक अंतर्निहित रूपांतरण करते हैं, तो आप अनिवार्य रूप से कह रहे हैं कि, क्या आप पहले स्थान पर एक्स लिखने पर पूर्ण नियंत्रण रखते थे, तो आप एक्स बनाते लागू करें या वाई का उप-वर्ग बनें।

यदि एक्स को कार्यान्वित करने के लिए एक्स समझ में आता है, तो रूपांतरण जोड़ें। यदि ऐसा नहीं होता है, तो शायद यह उचित नहीं है। उदाहरण के लिए, स्ट्रिंग के लिए RandomAccessSeq [Char] को कार्यान्वित करने के लिए यह समझ में आता है, लेकिन शायद स्ट्रिंग को कार्यान्वित करने के लिए स्ट्रिंग के लिए यह समझ में नहीं आता है (हालांकि स्ट्रिंगडेट को लागू करने वाला स्ट्रिंग ठीक लगता है)।

(मैं देर से एक छोटे से हूँ, और Flaviu एक शानदार जवाब है, लेकिन मैं इस बारे में मैं कैसे implicits के बारे में सोचना एक टिप्पणी जोड़ना चाहते थे।)