2011-01-31 11 views
11

निम्नलिखित कोड को परिभाषित करें:क्लासमैनिफेस्ट को ऐरे के साथ क्यों जरूरी है लेकिन सूची नहीं है?

scala> def test[T](iter:java.util.Iterator[Any], func:Any=>T):Array[T] = 
    | iter.map(i=>func(i)).toArray   

<console>:11: error: could not find implicit value for evidence parameter of 
type ClassManifest[T] 
    iter.map(i=>func(i)).toArray 
         ^

दूसरी ओर, का उपयोग कर नीचे दिए गए वैकल्पिक कोड:

import scala.collection.JavaConversions._ 
val iter:java.util.Iterator[Any] = Array[Any](1, 2, 3).iterator 
def func(a:Any):String = a.toString 

def test[T:ClassManifest](iter:java.util.Iterator[Any], func:Any=>T):Array[T] = 
    iter.map(i=>func(i)).toArray 

def testFunc = test(iter, func) 

यहाँ, मैं नहीं तो मैं त्रुटि मिलती है ClassManifest उपयोग करने के लिए इसे सही ढंग से संकलित करने के लिए के लिए की जरूरत है, List इसकी आवश्यकता नहीं है और ठीक से संकलित करता है।

import scala.collection.JavaConversions._ 
val iter:java.util.Iterator[Any] = Array[Any](1, 2, 3).iterator 
def func(a:Any):String = a.toString 

def test1[T](iter:java.util.Iterator[Any], func:Any=>T):List[T] = 
    iter.map(i=>func(i)).toList 


def testFunc1 = test1(iter, func).toArray 

ध्यान दें कि testFunc और testFunc1 के अंतिम उत्पादन समान हैं।

List संस्करण को ClassManifest की आवश्यकता नहीं है?

उत्तर

10

जावा में सरणी टाइप-मिस्ड नहीं हैं, और विशेष रूप से, Array[Int] JVM स्तर पर Array[Object] से भिन्न है।

किसी भी अन्य वर्ग के लिए, टाइप पैरामीटर Object पर मिटा दिए गए हैं, इसलिए List[Int] और List[Object] के पास JVM स्तर पर समान प्रतिनिधित्व है।

+0

आपका और एंजेल का जवाब एक साथ मिलकर सही जवाब बनाता है :) – Jus12

2

संक्षिप्त उत्तर है कि है, क्योंकि कैसे तरीकों defined in the API हैं:

def toArray [B >: A] (implicit arg0: ClassManifest[B]) : Array[B] 
def toList : List[A] 

आप अपने कोड में def test[T:ClassManifest] में :ClassManifest बंद छोड़ देते हैं, तो सभी संकलक जानता है कि यह किसी अज्ञात प्रकार है कि T और इसलिए कंपाइलर के पास उस प्रकार के लिए ClassManifest खोजने का कोई तरीका नहीं है।

कोड को ClassManifest क्यों चाहिए? आप look at the source for toArray तो आप देखेंगे:

val result = new Array[B](size) 

Array के इस निर्माता एक ClassManifest की आवश्यकता है। इस के प्रलेखन के लिए आसान एंजेल का जवाब देखें। यहाँ एक उदाहरण आरईपीएल में यह प्रदर्शन है:

scala> def createArray[T] = new Array[T](10) 
<console>:5: error: cannot find class manifest for element type T 
     def createArray[T] = new Array[T](10) 

तो मूल रूप से, आप क्योंकि स्काला आदेश एक नई सरणी बनाने के लिए एक ClassManifest जरूरत T: ClassManifest लिखने के लिए की है।

10

विधि toArrayT प्रकार के तत्वों के साथ नई सरणी बनाता है। और according to documentation:

So depending on the actual type parameter for T, this could be an Array[Int], or an Array[Boolean], or an array of some of the other primitive types in Java, or an array of some reference type. But these types have all different runtime representations, so how is the Scala runtime going to pick the correct one? In fact, it can't do that based on the information it is given, because the actual type that corresponds to the type parameter T is erased at runtime.

2

स्काला Array के लिए कार्यान्वयन के रूप में JVM देशी सरणियों उपयोग करता है। ऐसा केवल ज्ञात प्रकार के साथ बनाया जा सकता है।

चूंकि सूर्य ने विरासत कलाकृतियों को बनाने का फैसला किया है, सामान्य प्रकार मिटा दिए गए हैं और अब बाइट कोड में मौजूद नहीं हैं। इसका मतलब है कि रनटाइम पर, Array[T] अब T के मान को नहीं जानता है और इसलिए, वीएम सरणी नहीं बना सकता है। जब आप जावा 1.4 के अनुकूल होने का प्रयास करते हैं और सरणी पर जेनेरिक शुरू करते हैं तो मुझे कुछ और जटिल समस्याएं मिलती हैं (मुझे पूरी गहराई नहीं मिलती है), लेकिन नीचे की रेखा है: जेवीएम/जावा के सरणी सामान्य नहीं हैं; स्कैला हमें सामान्य अमूर्तता में मदद करता है।

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

+0

"संभवतः वस्तुओं को वास्तव में ढेर पर क्रमशः डाल दिया जाता है" नहीं, वे नहीं हैं। ऑब्जेक्ट्स की Arrays अनुक्रमिक रूप से संदर्भ संदर्भ, वस्तुओं को स्वयं नहीं। (यह निश्चित रूप से प्राइमेटिव के सरणी पर लागू नहीं होता है।) –

+1

अधिक अस्पष्ट तर्क के पक्ष में संपादित किया गया। पेंच विरासत, गंभीरता से ... – Raphael

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