2012-04-05 21 views
6

बाध्य प्रकार पैरामीटर Animal[A <: String] के साथ कक्षा परिभाषा को देखते हुए ऐसा लगता है कि स्कैला कंपाइलर Animal[B] से B <: String का अनुमान नहीं लगाता है। क्या अनुमान की अनुमति है? अनुमान लगाने के लिए कंपाइलर की मदद कैसे करें?केस क्लास को अनबाउंड प्रकार पैरामीटर वाले सदस्यों के साथ कैसे परिभाषित करें?

नीचे केस कक्षाओं के साथ एक ठोस उदाहरण है जहां इस अनुमान की कमी एक समस्या है।

sealed trait Person[+T <: Person[T]] 
case class Student() extends Person[Student] 
case class Professor() extends Person[Professor] 

मैं एक मामले वर्ग University जो मैं प्रकार Person[_] के एक चर के साथ का दृष्टांत सकते हैं, उदाहरण के लिए val p: Person[_] = Student() परिभाषित करने की जरूरत:

निम्नलिखित मामले वर्ग पदानुक्रम पर विचार करें। मुझे लगा कि यह निम्नलिखित परिभाषा के साथ काम करेगा:

case class University(p: Person[_]) 

लेकिन इस त्रुटि के साथ संकलन में विफल रहता है:

type arguments [Any] do not conform to trait Person's type parameter bounds [+T <: Person[T]] 

अगर मैं मामले वर्ग University यह संकलित के प्रकार के पैरामीटर बाँध (यह भी साथ संकलित असीम मापदंडों अगर मैं case कीवर्ड ड्रॉप लेकिन यह) मेरे मामले में एक विकल्प नहीं है:

case class BoundUniversity[P <: Person[P]](p: Person[P]) 

लेकिन इस parametrized संस्करण नहीं किया जा सकता

inferred type arguments [_$1] do not conform to method apply's type parameter bounds [P <: Person[P]] 

वही त्रुटि की तरह एक बाध्य तर्क के साथ एक विधि से होता है::

def general[P <: Person[P]](p: P) = println(p) 

तो यह है

val p: Person[_] = Student() 
BoundUniversity(p) 

विफल रहता है के साथ संकलन: प्रकार Person[_] का एक असीम चर के साथ instantiated वर्ग रचनाकारों के लिए विशिष्ट नहीं है।

दो सवाल:

  1. प्रकार Person, पैरामीटर सीमा Person[+T <: Person[T]] साथ परिभाषित किया गया है ताकि इस प्रकार के प्रत्येक उदाहरण के उन सीमा का सम्मान करने का बीमा किया जाता है: val p: Person[P] का तात्पर्य है कि P <: Person[P]; या क्या मैं कुछ न कुछ भूल रहा हूं? तो मैं संकलक को यह स्पष्ट कैसे कर सकता हूं ताकि वह शिकायत न करे?

  2. case class University(p: Person[_]) जैसे अनबाउंड प्रकार पैरामीटर वाले सदस्यों के साथ केस क्लास कैसे परिभाषित/कर सकता हूं?

+0

क्या टी को 'कॉरिएरिएंट होने की आवश्यकता है? – leedm777

+0

@ डेव मेरे विशेष मामले में 'टी' को कॉन्वेंटेंट होना चाहिए, लेकिन मुझे लगता है कि यह समस्या को नहीं बदलेगा: प्रारंभिक उदाहरण देखें। –

+0

आप कहीं भी [सार प्रकार] (http://docs.scala-lang.org/tutorials/tour/abstract-types.html) का उपयोग कर सकते हैं, लेकिन फिर वे [बहुत अधिक invariant] बन जाते हैं (http: // stackoverflow। com/एक/5359015/115,478)। – leedm777

उत्तर

2

एक प्रकार X[_] शायद ही कभी आप चाहते हैं। जब आप किसी प्रकार पर _ का उपयोग करते हैं, तो आप मूल रूप से कह रहे हैं कि आपको परवाह नहीं है कि पैरामीटर क्या है, क्योंकि आपको इसे कभी भी उपयोग करने की आवश्यकता नहीं होगी।

वैसे भी, यह संकलित करता है। यह आपको सड़क के नीचे अच्छी तरह से काट सकता है, अस्तित्वहीन प्रकार उन मुश्किल चीजें हैं जो वे हैं, लेकिन ...

case class University(p: Person[t] forSome { type t <: Person[t] }) 
+0

अच्छा अस्तित्व प्रकार, धन्यवाद! यह संकलित करता है, लेकिन 'वैल पी: व्यक्ति [_] = छात्र() के साथ तत्काल नहीं किया जा सकता है; विश्वविद्यालय (पी) '। जिस प्रकार का उल्लेख मैंने किया है वह व्यक्ति 'व्यक्ति [_]' सूची से आता है: 'सूची [व्यक्ति [_]] (छात्र(), प्रोफेसर()) '। ध्यान दें कि 'सूची (छात्र(), प्रोफेसर())' संकलित नहीं है। मुझे लगता है कि यहां एक पैटर्न है लेकिन मैं उस पर उंगली नहीं डाल सकता ... –

+0

असल में यह मेरे ग्रहण में त्रुटियों को नहीं दिखाता है लेकिन 'स्केलैक' के साथ संकलित नहीं करता है। मिस्मिच टाइप करें, 'व्यक्ति [(कुछ अन्य) _1 (विधि बराबर में)] जहां टाइप (कुछ अन्य) _1 (विधि बराबर में) <: schemdesc.hierarchy.eval.Person [_0] ', आवश्यक' व्यक्ति [_ < : schemdesc.hierarchy.eval.Person [_0]] ' –

+0

@jullybobble उपर्युक्त रेखा संकलित - मैंने इसका परीक्षण किया। यदि आपके पास संकलन समस्या है, तो आप कुछ अलग कर रहे हैं। और आप 'व्यक्ति [_] 'का उपयोग नहीं कर सकते - यह काम नहीं करेगा। यदि आप इसे काम करना चाहते हैं तो आपको ऊपर मौजूद अस्तित्व के प्रकार का उपयोग करना होगा। –