2011-07-12 7 views
6

शुभ दिन! मैं काफी स्केला के लिए नया हूँ इसलिए विकास के दौरान निम्नलिखित प्रश्न उठाया गया था:टाइप पैरामीट्रिजेशन या स्ट्रक्चरल सबटाइपिंग या

मैं वर्ग ट्री [टी], जहां टी प्रकार पैरामीटर है वर्णन करने के लिए चाहते हैं। लेकिन टी constrainted जाना चाहिए - यह 2 तरीकों होना चाहिए: (!): डीईएफ़ कुंजी() एक, जहां एक कुछ प्रकार, विधि के कार्यान्वयन और डीईएफ़ संघ से प्राप्त होता है (एक्स: टी): टी, जहां टी टाइप पैरामीटर के समान है। (दो लक्षण इन तरीकों में से स्वतंत्र स्वभाव की वजह से है)

  1. विधि कुंजी और विधि संघ साथ दूसरे के साथ दो लक्षण परिभाषित का उपयोग कर
  2. : मैं इस बाधा को कई तरह से व्यक्त किया जा सकता लगता है संरचनात्मक subtyping बाकी
  3. कुछ ...

तो मैं इसे कैसे प्रत्येक तरह से कर सकते हैं? और अन्य तरीके मौजूद हैं?

यह भी अच्छा होगा अगर इन तरीकों को सरल प्रकारों (जैसे स्ट्रिंग, इंट इत्यादि) के लिए जोड़ना आसान हो जाएगा।

उत्तर

5

आप key के लिए संरचनात्मक प्रकार को परिभाषित कर सकते हैं, लेकिन union के लिए नहीं। एक संरचनात्मक प्रकार अपने आप को परिभाषित अमूर्त प्रकारों का उल्लेख नहीं कर सकता है। तो यह काम करेगा नहीं:

trait Tree[T <: { def union(x: T): T }] 

आप एक ऐसी विशेषता है जो Tree के तत्वों उपलब्ध बनाने चाहिए, हालांकि परिभाषित कर सकते हैं:

trait TreeVal[T] { 
    type A 
    def key: A 
    def union(x: T): T 
} 

दो तरह इस्तेमाल किया जा सकता। सबसे पहले, कक्षाओं को उस इंटरफ़ेस को कार्यान्वित करना होगा, जो कि कुंजी के रूप में किन वर्गों का उपयोग किया जा सकता है, इस पर गंभीर बाधा डालती है।यह इस तरह होगा:

trait Tree[T <: TreeVal[T]] 

यह भी इस तरह, एक अंतर्निहित रूपांतरण के रूप में की पेशकश की जा सकती है:

class IntVal(v: Int) extends TreeVal[Int] { 
    type A = Int 
    def key: A = v 
    def union(x: Int): Int = x + v 
} 
implicit def IntIsVal(v: Int): IntVal = new IntVal(v) 

class Tree[T <% TreeVal[T]] // must be class, so it can receive parameters 

यह प्रयोग किया जाता है क्या बाध्य एक दृश्य कहा जाता है। इसे अधिक जानकारी के लिए देखें, लेकिन यह कहने के लिए पर्याप्त है कि आप किसी भी तरह का इलाज करने में सक्षम होंगे जिसमें एक निहित रूपांतरण परिभाषित किया गया है और दायरे में जैसे कि यह TreeVal था। उदाहरण के लिए:

class Tree[T <% TreeVal[T]](node: T, left: Option[Tree[T]], right: Option[Tree[T]]) { 
    override def toString = "(%s < %s > %s)" format (left.getOrElse("o"), node.key, right.getOrElse("o")) 
} 

वैकल्पिक रूप से, आप इसे प्रकार वर्ग पैटर्न के साथ उपयोग कर सकते हैं, कुछ परिवर्तनों के साथ:

trait TreeVal[T] { 
    type A 
    def key(v: T): A 
    def union(x: T, y: T): T 
} 
class Tree[T : TreeVal] // must be class, so it can receive parameters 

प्रकार वर्ग पैटर्न संदर्भ सीमा का उपयोग करता है। अधिक जानकारी के लिए देखो। इस शैली को आम तौर पर आजकल पूर्व शैली पर प्राथमिकता दी जाती है, क्योंकि यह कई तरीकों से अधिक लचीला है। फिर भी, दोनों काम करेंगे।

इस मामले में, एक इसे इस तरह का प्रयोग करेंगे:

implicit object IntVal extends TreeVal[Int] { 
    type A = Int 
    def key(v: Int) = v 
    def union(x: Int, y: Int) = x + y 
} 

class Tree[T: TreeVal](node: T, left: Option[Tree[T]], right: Option[Tree[T]]) { 
    val treeVal = implicitly[TreeVal[T]] 
    import treeVal._ 

    override def toString = "(%s < %s > %s)" format (left.getOrElse("o"), key(node), right.getOrElse("o")) 
} 
+0

उत्कृष्ट स्पष्टीकरण, बहुत बहुत धन्यवाद! – newf

+0

लेकिन एक और सवाल: मुझे 'अंतर्निहित वस्तु IntVal' में स्पष्ट रूप से 'टाइप ए' निर्दिष्ट क्यों करना चाहिए? क्या इसे 'डीफ कुंजी' परिभाषा से अनुमानित किया जा सकता है? – newf

+0

हो सकता है कि आप विधि 'कुंजी' के पैरामीट्रिज्ड संस्करण का उपयोग कर सकें:' def key [ए]: ए' – incrop

2

संरचनात्मक प्रकार जावा प्रतिबिंब के साथ कार्यान्वित किए जाते हैं, इसलिए वे प्रदर्शन को कम कर देंगे। स्क्रिप्ट जैसे छोटे कार्यक्रमों के लिए, या प्रारंभिकरण के लिए यह ठीक है, लेकिन कोई गहन उपयोग आपको प्रोग्राम को घुटनों पर ला सकता है ...

तो मैं आपको पहला विकल्प चुनूंगा। आपको कम से कम दो प्रकार के पैरामीटर की आवश्यकता होगी। लेकिन आप केवल एक विशेषता के साथ जा सकते हैं यदि आप एक अधिक विस्तृत रूप से की जरूरत नहीं है:

trait Tree[T,A] { 
    def key(): A 
    def union(x: T): T 
} 
+0

ऐसा लगता है वह चाहता है की तरह तरीकों 'T' के बजाय' Tree' पर परिभाषित किया जा करने के लिए। –

3

आप करने के लिए सरल प्रकार के लिए इन तरीकों "जोड़ें" में सक्षम होना चाहते हैं, तो हो सकता है आप का उपयोग कर बेहतर होगा कक्षाएं टाइप करें। Read more about type classes in this question, और केविन राइट के उत्तर को देखें, जो दिखाता है कि zero और append विधि को Int और String पर कैसे जोड़ें।

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