मेरे पास निम्नलिखित कथन हैं।
val a: Any = Array("1", "2", "3")
a match {
case p: Array[Int] => println("int")
case l: Array[String] => println("string")
}
val b: Any = List(1, 2, 3)
b match {
case l: List[String] => println("string")
case p: List[Int] => println("int")
}
ऐरे के बारे में पहला ब्लॉक चेतावनी और आउटपुट "स्ट्रिंग" के बिना संकलित करता है, जबकि सूची के बारे में दूसरा एक प्रकार इरेज़ से संबंधित चेतावनियों के साथ संकलन करता है और "स्ट्रिंग" के रूप में अच्छी तरह से आउटपुट करता है।
मुझे JVM में टाइप इरेज़र के बारे में कुछ पता है। रनटाइम के दौरान, JVM वास्तव में एक कंटेनर के सामान्य प्रकार (जैसे सूची) को नहीं जान सकता है। लेकिन अर्रे रनटाइम में टाइप एरेस्योर से क्यों बच सकते हैं और सही प्रकार से मेल खाते हैं?
मैंने स्कैला सोर्स कोड से जवाब खोजने की कोशिश की। केवल एक चीज मुझे मिली है कि एरे क्लासटैग का उपयोग करता है लेकिन सूची नहीं करता है।
मुझे पसंद है कि क्लासटैग कैसे काम करता है। क्या क्लासटैग टाइप इरेज़र का वर्कअराउंड है? और लिस्ट हेवन जैसे कंटेनरों को टाइप एग्योर से बचने के लिए क्लासटैग के साथ क्यों लागू किया गया है।
उत्तर:
उत्तर № 1 के लिए 4स्काला जेवीएम पर चलता है और उसे विरासत में मिला हैबाधाओं। जावा प्रकार के क्षरण को नियोजित करता है इसलिए सभी पैराट्राइज्ड प्रकार रनटाइम में समान होते हैं। प्रकार की जानकारी उनसे मिट जाती है। यह पुराने जावा संस्करणों के साथ संगतता रखने के लिए किया गया था जो कि प्रकार के मापदंडों का उपयोग नहीं कर सकते थे।
लेकिन सरणियाँ जावा में विशेष मामला है, वे प्रकार की जानकारी रखते हैं। तो स्कैला एरेज़ करते हैं। यह जरूरी है कि एरेज़ के अंदर मेमोरी कुशल अनबॉक्स्ड वैल्यूज़ रखें।
आपको बस यह मान लेना चाहिए कि रनटाइम के दौरान सभी प्रकार की जानकारी खो जाती है। इसलिए उनके खिलाफ मिलान करने के लिए कुछ टैग का उपयोग करें।
ClassTag
s सरणी रैपिंग से संबंधित नहीं हैं। सभी प्रकार की जानकारी JVM द्वारा ही प्रदान की जाती है।
AnyRef का उपयोग करने के लिए जावा में कस्टम प्रैक्टिस हैऔर गतिशील कलाकारों को हर बार आपको संबंधों को व्यक्त करने में कठिनाइयाँ आती हैं। स्काला रनटाइम रूपांतरणों के बिना सांख्यिकीय रूप से वर्णन करने के लिए अधिक अभिव्यंजक शक्ति प्रदान करता है। और स्काला कोडिंग शैली कोड प्रकारों को रखने के लिए भारी प्रकार के निर्माणों का उपयोग करने के लिए प्रोत्साहित करती है।
ClassTag
रेत TypeTag
s ऐसे इंस्ट्रूमेंट हैं जिनका उपयोग केवल के साथ किया जा सकता हैसांख्यिकीय रूप से टाइप किया गया कोड। उनके पास वर्ग और प्रकार की जानकारी है जो संकलन समय के दौरान संकलक ने प्राप्त की है। अगर यह प्रकारों को वैधानिक रूप से प्राप्त कर सकता है तो यह आपके लिए इस प्रकार तक पहुँचने के लिए टाइप टैग प्रदान कर सकता है।
यह उपयोगी है जब आप किसी तरह की लाइब्रेरी लिखते हैं और इसका कोई सुराग नहीं होता है कि इसका उपयोग कैसे किया जाएगा। तो आपको आवश्यकता है ClassTag
निहित पैरामीटर के रूप में और यह द्वारा भरा जाएगाफंक्शन कॉल को दिए गए अन्य तर्क पर उपयुक्त प्रकार के आधार के साथ संकलक। इंप्लांट मापदंडों को लाइब्रेरी कोड द्वारा आवश्यकता के रूप में रखा गया है और लाइब्रेरी को कॉल करने वाले बाहरी कोड द्वारा स्वचालित रूप से भरा जाता है।
जवाब के लिए 0 № 2
इन मामलों में आप का उपयोग करने पर विचार कर सकते हैं Typeable
प्रकार वर्ग आप के साथ मिल निराकार प्रकार सुरक्षित casts के लिए । जैसे.:
scala> import shapeless.syntax.typeable._
import shapeless.syntax.typeable._
scala> val b: Any = List(1, 2, 3)
b: Any = List(1, 2, 3)
scala> b.cast[List[String]]
res1: Option[List[String]] = None
scala> b.cast[List[Int]]
res2: Option[List[Int]] = Some(List(1, 2, 3))
जैसा कि आप कर सकते है cast[T]
विधि, के माध्यम से निराकार द्वारा हर प्रकार के लिए जोड़ा implicits
, रिटर्न एक Option[T]
जिसका मूल्य है None
यदि कास्ट विफल रहता है, Some
यदि यह "सफल एस ।
यदि आपको ऐसा लगता है कि आप स्रोत कोड देख सकते हैं typeable। हालाँकि, मेरा सुझाव है कि ऐसा करने से पहले आपको एक अच्छा कप कॉफी मिल जाए। :)