2011-07-13 23 views
13

मान लीजिए कि मैं स्कैला में टाइपक्लास पैटर्न का उपयोग कर रहा हूं।मैं टाइपटास पैटर्न को सबटाइपिंग के साथ कैसे जोड़ सकता हूं?

Welcome to Scala version 2.9.0.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26). 

scala> trait Foo[T] { def foo(t: T) } 
defined trait Foo 

scala> def foo[T : Foo](t: T) { implicitly[Foo[T]].foo(t) } 
foo: [T](t: T)(implicit evidence$1: Foo[T])Unit 

scala> class C 
defined class C 

scala> foo(new C) 
<console>:11: error: could not find implicit value for evidence parameter of type Foo[C] 
     foo(new C) 
     ^

scala> implicit object FooC extends Foo[C] { override def foo(c: C) { println("it's a C!") } } 
defined module FooC 

scala> foo(new C) 
it's a C! 

अब तक तो अच्छा: यहाँ मैं कैसे typeclass फू के एक वर्ग सी हिस्सा बनाते हैं। लेकिन मैं सी के एक उपवर्ग डी है लगता है, और मैं typeclass "में" भी होने के लिए डी के उदाहरण हैं:

scala> class D extends C 
defined class D 

scala> foo(new D) 
<console>:13: error: could not find implicit value for evidence parameter of type Foo[D] 
     foo(new D) 
     ^

रवींद्र! डी के लिए एक टाइपक्लास उदाहरण स्पष्ट रूप से प्रदान किए बिना मैं यह काम कैसे करूं?

+0

याद किया यह काफी http का डुप्लिकेट है: // stackoverflow। कॉम/प्रश्न/3869 991/टाइप-क्लास-पैटर्न-इन-स्कैला-डेंट-विचार-विरासत –

उत्तर

14

इस के लिए विभिन्न संभव समाधान है, चाहे मैं केवल सी के लिए समस्या ठीक करने के लिए चाहते हैं पर निर्भर करता है, या मैं पूरे typeclass के लिए समस्या को ठीक करना चाहते हैं।

सी ही, implicit object FooC ... के बजाय के लिए हम कहते हैं:

implicit def CIsFoo[T <: C]: Foo[T] = 
    new Foo[T] { override def foo(t: T) { println("it's a C!") } } 

फू के सभी ठीक करने के लिए, यह contravariant:

trait Foo[-T] { def foo(t: T) } 

या अगर किसी कारण से आप नहीं कर सकते हैं या डॉन ' टी कि क्या करना चाहते हैं, आप के साथ def foo... की जगह ले सकता:

def foo[T](t: T)(implicit foo: Foo[_ >: T]) = 
    foo.foo(t) 

(धन्यवाद निवासी #scala को । एस डैनियल Sobral और स्टीफन Zeiger उनकी मदद के लिए)

UPDATED सितं, 20 2011 "फू contravariant बनाने के" समाधान शामिल करने के लिए है, जो मैं

+1

यहां एक और सवाल है जो छिप रहा है ... यदि मैं चाहता हूं कि टी को टी से अलग तरीके से व्यवहार किया जाए, * लेकिन * कुछ सामान्य कोड साझा करें ! – jsuereth

+3

@jsuereth कुछ भी आपको 'डी' के लिए 'डी' के लिए' अंतर्निहित वस्तु FooD' घोषित करने से रोकता है, और 'FooD' में 'FooC' से कॉल विधियों को कॉल करता है। –

+1

दरअसल आपको इसे आजमा देना चाहिए। जब तक आप प्राथमिकताओं के साथ मिल नहीं जाते हैं, 'विवादित अंतर्निहित आयात'। पूरा समाधान सुंदर बॉयलर-प्लेटी दिखता है और साथ में मक्खन के लिए निराशाजनक हो सकता है। – jsuereth