2011-09-23 13 views
11

प्रोग्रामेटिक रूप से यह निर्धारित करने के लिए कि क्या दिया गया वर्ग केस क्लास या साधारण श्रेणी है?प्रोग्रामेटिक रूप से यह निर्धारित करने के लिए कि कक्षा एक केस क्लास या साधारण वर्ग है या नहीं?

उत्तर

2

वर्तमान में (2011), आप वर्ग इंटरफ़ेस scala.Product लागू करता है यदि पता लगाने के लिए प्रतिबिंब का उपयोग कर सकते हैं:

scala> def isCaseClass(o: AnyRef) = o.getClass.getInterfaces.find(_ == classOf[scala.Product]) != None 
isCaseClass: (o: AnyRef)Boolean 

scala> isCaseClass(Some(1)) 
res3: Boolean = true 

scala> isCaseClass("") 
res4: Boolean = false 

यह सिर्फ एक सन्निकटन है - आप आगे जाकर जांचें कि क्या इसका copy विधि है सकता है, यदि यह Serializable लागू करता है, यदि उसके पास उचित apply या unapply विधि के साथ एक साथी ऑब्जेक्ट है - संक्षेप में, प्रतिबिंब का उपयोग करके केस क्लास से अपेक्षित सभी चीजों की जांच करें।

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

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

अब आप यह नया स्काला प्रतिबिंब लाइब्रेरी का उपयोग कर सकते हैं - अन्य उत्तर देखें।

+0

धन्यवाद, axel22। यह मेरी समस्या का समाधान है। मुझे उम्मीद है कि डेवलपर्स जल्द से जल्द स्कैला की इस विधि को जोड़ देंगे। Сlass इंटरफेस scala लागू करता है। उत्पाद - यह इसके लिए एक पर्याप्त शर्त है? – DimParf

+0

नहीं, यह जांचने के लिए कोई पर्याप्त शर्त नहीं है (afaik)।आप मूल कोड में 'केस' संशोधक के अस्तित्व की जांच नहीं कर सकते हैं, केवल 'केस' संशोधक के कारण उत्पन्न होने वाली विधियों के लिए। जैसा कि मैंने उपरोक्त लिखा है, पूरी बात सिर्फ एक अनुमान है। – axel22

2

यदि आपका मतलब है: क्या मैं निर्धारित कर सकता हूं कि कक्षा एक केस क्लास या गैर-केस क्लास प्रोग्रामेटिक रूप से है, तो जवाब नहीं है, लेकिन आप अनुमान लगा सकते हैं। केस क्लासेस सिर्फ एक कंपाइलर हैक हैं, वे कुछ तरीकों को बनाने के लिए कंपाइलर को बताते हैं। अंतिम बाइटकोड में, सामान्य कक्षाओं और केस क्लास के बीच कोई अंतर नहीं है।

से How does a case class differ from a normal class?

  1. ,
  2. आप पैटर्न उस पर मिलान कर सकते हैं आप नए कीवर्ड का उपयोग किए बिना इन कक्षाओं के उदाहरण का निर्माण कर सकते,
  3. सभी निर्माता तर्क के बाहर का उपयोग करने से जाया जा सकता है स्वचालित रूप से जेनरेट किए गए एक्सेसर फ़ंक्शंस,
  4. टूस्ट्रिंग विधि स्वचालित रूप सेनाम मुद्रित करने के लिए फिर से परिभाषित की जाती है केस क्लास केऔर उसके सभी तर्क,
  5. बराबर विधि स्वचालित रूप से दो तुलनात्मक रूप से पहचान के बजाय समान केस वर्ग के उदाहरणों की तुलना करने के लिए फिर से परिभाषित की जाती है।
  6. हैशकोड विधि कन्स्ट्रक्टर तर्कों के हैशकोड का उपयोग करने के लिए स्वचालित रूप से फिर से परिभाषित की जाती है।

तो तुम वास्तव में सिर्फ सही तरीकों & साथी खुद वस्तुओं को परिभाषित करते हुए एक मामला वर्ग बना सकते हैं।

एक विचार के लिए कि कैसे एक वर्ग एक केस क्लास हो सकता है, axel22 से उत्तर देखें।

16

नई स्काला प्रतिबिंब एपीआई का उपयोग करना:

scala> class B(v: Int) 
defined class B 

scala> case class A(v: Int) 
defined class A 

scala> def isCaseClassOrWhat_?(v: Any): Boolean = { 
    | import reflect.runtime.universe._ 
    | val typeMirror = runtimeMirror(v.getClass.getClassLoader) 
    | val instanceMirror = typeMirror.reflect(v) 
    | val symbol = instanceMirror.symbol 
    | symbol.isCaseClass 
    | } 
isCaseClassOrWhat_$qmark: (v: Any)Boolean 

scala> class CaseClassWannabe extends Product with Serializable { 
    | def canEqual(that: Any): Boolean = ??? 
    | def productArity: Int = ??? 
    | def productElement(n: Int): Any = ??? 
    | } 
defined class CaseClassWannabe 

scala> isCaseClassOrWhat_?("abc") 
res0: Boolean = false 

scala> isCaseClassOrWhat_?(1) 
res1: Boolean = false 

scala> isCaseClassOrWhat_?(new B(123)) 
res2: Boolean = false 

scala> isCaseClassOrWhat_?(A(321)) 
res3: Boolean = true 

scala> isCaseClassOrWhat_?(new CaseClassWannabe) 
res4: Boolean = false 
संबंधित मुद्दे

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