2010-04-28 7 views
8

के विरासत और प्रकार पैरामीटर मैं स्कैला 2.8 संग्रह कक्षाओं के स्रोत कोड का अध्ययन कर रहा हूं। मेरे पास scala.collection.Traversable के पदानुक्रम के बारे में प्रश्न हैं। निम्नलिखित घोषणाओं को देखो:ट्रैवर्सबल

package scala.collection 
    trait Traversable[+A] 
     extends TraversableLike[A, Traversable[A]] 
     with GenericTraversableTemplate[A, Traversable] 

    trait TraversableLike[+A, +Repr] 
     extends HasNewBuilder[A, Repr] 
     with TraversableOnce[A] 

package scala.collection.generic 
    trait HasNewBuilder[+A, +Repr] 

    trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] 
     extends HasNewBuilder[A, CC[A] @uncheckedVariance] 

प्रश्न: क्यों Traversable प्रकार पैरामीटर [A, Traversable] साथ GenericTraversableTemplate का विस्तार करता है - क्यों नहीं [A, Traversable[A]]? मैं एक ही संरचना के साथ एक छोटे से कार्यक्रम के साथ कुछ प्रयोग करने की कोशिश की और एक अजीब त्रुटि संदेश मिल गया जब मैं Traversable[A] करने के लिए इसे बदलने की कोशिश की:

error: Traversable[A] takes no type parameters, expected: one 

मुझे लगता है कि GenericTraversableTemplate में @uncheckedVariance एनोटेशन का प्रयोग भी साथ क्या करना है इस? (यह काम करने के लिए मजबूर करने के लिए संभावित रूप से असुरक्षित हैक की तरह लगता है ...)।

संपादित - this question में एनोटेशन बारे में कुछ उपयोगी जवाब मिल गया (ऐसा इसलिए है क्योंकि GenericTraversableTemplate दोनों परिवर्तनशील और अपरिवर्तनीय संग्रह जो विभिन्न विचरण है के लिए प्रयोग किया जाता है)।

प्रश्न: आप पदानुक्रम को देखते हैं, आप देखते हैं कि Traversable inherits HasNewBuilder दो बार (एक बार TraversableLike के माध्यम से और एक बार GenericTraversableTemplate के माध्यम से), लेकिन थोड़ा अलग प्रकार मानकों के साथ। यह वास्तव में कैसे काम करता है? विभिन्न प्रकार के पैरामीटर एक त्रुटि क्यों नहीं करते हैं?

उत्तर

16

विशेषता में CC पैरामीटर का कारण है। एक सामान्य प्रकार पैरामीटर के विपरीत, जिसमें * (उच्चारण "प्रकार") है, इस पैरामीटर में * => * (उच्चारण "प्रकार टाइप करें") है। इसका अर्थ समझने के लिए, आपको पहले प्रकारों के बारे में थोड़ी सी पृष्ठभूमि की आवश्यकता है।

val a: Int = 42 

यहाँ हम 42 देखना है, जो एक मूल्य है:

निम्नलिखित स्निपेट पर विचार करें। मूल्यों में आंतरिक प्रकार हैं। इस मामले में, हमारा मान 42 है और प्रकार Int है। एक प्रकार एक श्रेणी की तरह कुछ है जिसमें कई मूल्य शामिल हैं। यह वैरिएबल a के लिए संभव मानों के बारे में कुछ कहता है। उदाहरण के लिए, हम जानते हैं कि a में मूल्य "foobar" नहीं हो सकता है, क्योंकि उस मान में String है। इस प्रकार, मूल्य अमूर्तता के पहले स्तर की तरह हैं, जबकि प्रकार मूल्यों के ऊपर एक स्तर हैं।

तो यहां सवाल है: हमें एक कदम आगे लेने से क्या रोक रहा है? यदि मूल्यों में प्रकार हो सकते हैं, तो उनके ऊपर "कुछ" प्रकार क्यों नहीं हो सकते हैं? उस "कुछ" को दया कहा जाता है। प्रकारों को टाइप करना है कि किस प्रकार के मूल्य हैं, जेनेरिक श्रेणियां जो प्रकार को किस प्रकार प्रतिबंधित करती हैं, को प्रतिबंधित कर सकते हैं। कुछ ठोस उदाहरण पर

आइए नज़र:

type String 
type Int 
type List[Int] 

इन प्रकार के हैं, और वे सभी प्रकार के * है। यह सबसे आम प्रकार है (यही कारण है कि हम इसे "टाइप" कहते हैं)। व्यवहार में, अधिकांश प्रकार इस तरह के होते हैं।हालांकि, कुछ नहीं है:

type List  // note: compile error 

यहाँ हम प्रकार निर्माता List है, लेकिन इस बार हम "भूल" अपने प्रकार पैरामीटर निर्दिष्ट करने के लिए। जैसा कि यह पता चला है, यह वास्तव में एक प्रकार है, लेकिन एक अलग तरह का है। विशेष रूप से, * => *। चूंकि नोटेशन का मतलब है, इस प्रकार एक प्रकार का वर्णन करता है जो एक और प्रकार का * पैरामीटर के रूप में लेता है, जिसके परिणामस्वरूप एक नया प्रकार * उत्पन्न होता है। हम इसे पहले उदाहरण में देख सकते हैं, जहां हमने प्रकार (जिसमें * है) List प्रकार कन्स्ट्रक्टर (जिसमें * => * है) टाइप किया गया है, जिस प्रकार List[Int] (जिसका प्रकार * है) का उत्पादन किया गया है।

GenericTraversableTemplate में लौटने के बाद की घोषणा पर फिर से नजर डालते हैं:

trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] 

सूचना कैसे CC प्रकार पैरामीटर की अपनी एक पैरामीटर लेता है, लेकिन उस पैरामीटर घोषणा में किसी भी अन्य प्रकार पैरामीटर द्वारा परिभाषित नहीं है? यह स्कैला का यह कहने का बेकार तरीका है कि CC दयालु * => * होना चाहिए (जैसे a हमारे पहले उदाहरण में Int प्रकार होना चाहिए)। "सामान्य" प्रकार पैरामीटर (जैसे A) हमेशा * प्रकार के होते हैं। CC को * => * के प्रकार के लिए मजबूर कर, हम प्रभावी ढंग से संकलक को बता रहे हैं कि इस पैरामीटर के लिए प्रतिस्थापित किए जाने वाले एकमात्र वैध प्रकारों को स्वयं * => * का होना चाहिए। इस प्रकार:

type GenericTraversableTemplate[String, List]  // valid! 
type GenericTraversableTemplate[String, List[Int]] // invalid! 

याद रखें, List की है प्रकार * => * (हम CC के लिए वास्तव में क्या जरूरत है), लेकिन List[Int] तरह * है, तो संकलक यह खारिज कर दिया।

रिकॉर्ड के लिए, GenericTraversableTemplate स्वयं का एक प्रकार है, विशेष रूप से: (* x (* => *)) => *। इसका अर्थ यह है कि GenericTraversableTemplate एक प्रकार है जो पैरामीटर के रूप में दो प्रकार लेता है - * में से एक, अन्य * => * के प्रकार - और परिणामस्वरूप * प्रकार का उत्पादन करता है। ऊपर दिए गए हमारे उदाहरण में, GenericTraversableTemplate[String, List] एक ऐसा परिणाम प्रकार है, और जैसा कि हमने गणना की है, यह * है (इसमें कोई पैरामीटर नहीं है)।

+0

इस उत्तर का उत्तर देने के लिए समय निकालने के लिए धन्यवाद! मैंने पहले "प्रकार" के बारे में सुना होगा लेकिन वास्तव में यह समझ में नहीं आया कि अब तक उनका क्या मतलब है। – Jesper