2016-07-30 2 views
6

मैं कक्षा जनरेटर (एवरो मॉडल के लिए) बनाना चाहता हूं। मुझे एक समस्या है क्योंकि कभी-कभी कक्षा के क्षेत्र का क्षेत्र कई अलग-अलग प्रकारों में से एक हो सकता है, मान लें कि यह Int या String या जो भी हो सकता है। सरल विचार है कि उस क्षेत्र को Any टाइप करें और रनटाइम पर जांचें कि यह ठीक है।संघ के प्रकार के लिए किसी का भी अच्छा विचार है?

समस्या यह है कि Any का उपयोग स्कैला प्रकार प्रणाली की कुछ शक्तिशाली विशेषताओं को छोड़ दें। कोड में कुछ बग संकलन समय पर पकड़े नहीं जाएंगे (अगर मैं String या IntAny द्वारा कवर किए गए फ़ंक्शन में List देता हूं।

उदाहरण के लिए:

आइए मैं अपने वर्ग के इस विवरण है:

class MyClass(myField: Any) 

मैं कुछ इस तरह बनाना चाहते हैं:

{"className" : "MyClass", "fields" : [ 
    { "fieldName" : "myField", "type" : ["String", "Int"]} 
]} 

इस विवरण से, मैं इस वर्ग बनाने :

class MyClass(myField: String or Int) 

क्या मुझे Any का उपयोग करना बंद कर देना चाहिए? Any का उपयोग आमतौर पर स्कैला समुदाय में एक अच्छा विचार माना जाता है?

+0

क्या पॉलिमॉर्फिक वर्ग नहीं बनाते? 'कक्षा फू [टी] ' –

+0

समस्या यह है कि मेरे पास कोई सुराग नहीं है कि फ़ील्ड कितने अलग-अलग प्रकार ले सकता है या यदि विभिन्न प्रकार एक सामान्य विशेषता साझा करते हैं। – Moebius

+3

'किसी भी' का उपयोग करना शायद ही कभी एक अच्छा विचार है। हालांकि, अधिक संदर्भ के बिना सलाह देना मुश्किल है। –

उत्तर

3

किसी भी आम तौर पर स्कैला समुदाय में एक अच्छा विचार माना जाता है?

नहीं। Any का मतलब कोई प्रकार की जानकारी नहीं है, इसलिए इसे आम तौर पर खराब अभ्यास माना जाता है।

स्कैला में आप Either का उपयोग कर एक यूनियन प्रकार व्यक्त कर सकते हैं, हालांकि यदि आपके पास संघ में बहुत से संभावित प्रकार हैं तो यह बोझिल हो जाता है। उदाहरण:

class MyClass(myField: Either[String, Int]) { 
    def doSomething = myField match { 
    case Left(myStringField) => ??? 
    case Right(myIntField) => ??? 
    } 
} 

एक और व्यवहार्य दृष्टिकोण MyClass अपने प्रकार में सामान्य बनाने के लिए होगा:

class MyClass[A](myField: A) 

हालांकि इस A के प्रकार पर किसी भी बाधा की स्थापना नहीं है।

एक बाधा डालने के लिए, उदा। यह प्रकार की एक निश्चित सबसेट बनाने के लिए, आप तदर्थ बहुरूपता का उपयोग कर सकते हैं:

trait MyConstraint[A] 
class MyClass[A: MyConstraint](myField: A) 

अब new MyClass(myValue) संकलन नहीं होगा जब तक कि वहाँ है दायरे में एक अंतर्निहित MyConstraint[A]। अब आप प्रकार श्वेत सूची में डालने कर सकते हैं निहित मूल्यों

का उपयोग कर की अनुमति देना चाहते
implicit object IntConstraint extends MyConstraint[Int] 
implicit object StringConstraint extends MyConstraint[String] 

उदाहरण:

new MyClass(42) // ok, there's implicit evidence of MyConstraint[Int] 
new MyClass("foo") // ok, there's implicit evidence of MyConstraint[String] 
new MyClass(false) // won't compile, no implicit evidence of MyConstraint[Boolean] 

तकनीकी शब्दों में, MyConstraint एक प्रकार वर्ग, MyClass के निर्माता में टाइप A परिष्कृत करने के लिए प्रयोग किया जाता है ।

आप एक प्रकार की कक्षा को और भी आगे की विशेषता दे सकते हैं, इसके संचालन के एक सेट को इसके प्रत्येक उदाहरण के लिए परिभाषित किया गया है। जैसे

trait MyConstraint[A] { 
    def mandatoryOp: A 
} 

implicit object IntConstraint extends MyConstraint[Int] { 
    def mandatoryOp = 42 
} 

implicit object StringConstraint extends MyConstraint[String] { 
    def mandatoryOp = "foo" 
} 

class MyClass[A](myField: A)(implicit ev: MyConstraint[A]) { 
    def doSomething: A = ev.mandatoryOp 
} 

कृपया ध्यान दें कि A: MyConstraint प्रकार MyConstraint[A] का एक अंतर्निहित पैरामीटर की आवश्यकता होती है के लिए बस वाक्यात्मक चीनी है। आखिरी उदाहरण में मैंने निहित पैरामीटर ev दायरे में उपलब्ध होने के लिए स्पष्ट वाक्यविन्यास चुना है।

+0

एडीटी पैटर्न का कोई उल्लेख क्यों नहीं? यह यहां सबसे उपयुक्त दृष्टिकोण की तरह लगता है। – Jubobs

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