आम तौर पर, एक सहसंयोजक प्रकार पैरामीटर वह होता है जिसे अलग-अलग करने की अनुमति दी जाती है क्योंकि वर्ग को उप-प्रकार दिया जाता है (वैकल्पिक रूप से, उपप्रकार के साथ भिन्न होता है, इसलिए "सह-" उपसर्ग)। अधिक संक्षिप्त:
trait List[+A]
List[Int]
का उप-प्रकार है List[AnyVal]
क्योंकि Int
इसका उप-प्रकार है AnyVal
। इसका मतलब है कि आप एक उदाहरण प्रदान कर सकते हैं List[Int]
जब एक प्रकार List[AnyVal]
का मूल्य अपेक्षित होता है। जेनरिक के लिए काम करने के लिए यह वास्तव में एक बहुत ही सहज तरीका है, लेकिन यह पता चलता है कि यह उत्परिवर्तित है (टाइप सिस्टम को तोड़ता है) जब उत्परिवर्तनीय डेटा की उपस्थिति में उपयोग किया जाता है। यही कारण है कि जावा में जेनेरिक अपरिवर्तनीय हैं। जावा सरणियों (जो त्रुटिपूर्ण रूप से सहसंयोजक हैं) का उपयोग करते हुए बेईमानी का संक्षिप्त उदाहरण:
Object[] arr = new Integer[1];
arr[0] = "Hello, there!";
हमने केवल एक प्रकार के प्रकार String
को एक मान दिया हैInteger[]
। जिन कारणों से यह स्पष्ट होना चाहिए, यह बुरी खबर है। जावा का टाइप सिस्टम वास्तव में संकलन के समय इसकी अनुमति देता है। JVM ArrayStoreException
रन टाइम पर "मददगार" होगा । स्काला का प्रकार सिस्टम इस समस्या को रोकता है क्योंकि Array
वर्ग पर टाइप पैरामीटर अपरिवर्तनीय है (घोषणा इसके [A]
बजाय है [+A]
)।
ध्यान दें कि एक अन्य प्रकार का विचरण है, जिसे कंट्रोवर्सी के रूप में जाना जाता है । यह बहुत महत्वपूर्ण है क्योंकि यह बताता है कि सहसंयोजक कुछ मुद्दों का कारण क्यों बन सकता है। कंट्रोवर्सी का शाब्दिक रूप से कोविरियन के विपरीत है: पैरामीटर भिन्न होते हैं उपप्रकार के साथ हैं । यह आंशिक रूप से बहुत कम आम है क्योंकि यह इतना सहज है, हालांकि इसमें एक बहुत महत्वपूर्ण अनुप्रयोग है: कार्य।
trait Function1[-P, +R] {
def apply(p: P): R
}
प्रकार पैरामीटर पर " - " विचरण एनोटेशन पर ध्यान दें P
। यह घोषणा एक पूरे साधन के रूप में होती है, जिसमें Function1
अंतर्विरोधी P
और अंदर सहसंयोजक होता है R
। इस प्रकार, हम निम्नलिखित स्वयंसिद्ध व्युत्पन्न कर सकते हैं:
T1' <: T1
T2 <: T2'
---------------------------------------- S-Fun
Function1[T1, T2] <: Function1[T1', T2']
ध्यान दें कि T1'
एक उपप्रकार (या उसी प्रकार का) होना चाहिए T1
, जबकि यह इसके लिए विपरीत है T2
और T2'
। अंग्रेजी में, इसे निम्नलिखित के रूप में पढ़ा जा सकता है:
एक फ़ंक्शन A दूसरे फ़ंक्शन B का उपप्रकार है, यदि A का पैरामीटर प्रकार B के प्रकार का पैरामीटर है, जबकि A का वापसी प्रकार B के प्रकार का एक उपप्रकार है ।
इस नियम का कारण पाठक को एक अभ्यास के रूप में छोड़ दिया गया है (संकेत: विभिन्न मामलों के बारे में सोचें क्योंकि फ़ंक्शन उप-प्रकार हैं, जैसे ऊपर से मेरा सरणी उदाहरण)।
सह-और विरोधाभासी के अपने नए-ज्ञान के साथ, आपको यह देखने में सक्षम होना चाहिए कि निम्नलिखित उदाहरण क्यों संकलित नहीं होंगे:
trait List[+A] {
def cons(hd: A): List[A]
}
समस्या यह है कि A
सहसंयोजक है, जबकि cons
फ़ंक्शन अपेक्षा करता है कि इसका प्रकार पैरामीटर अपरिवर्तनीय है । इस प्रकार, A
गलत दिशा बदलती है। दिलचस्प रूप से पर्याप्त है, हम इस समस्या को List
कॉन्ट्रावरीएन्ट बनाकर हल कर सकते हैं A
, लेकिन फिर रिटर्न प्रकार List[A]
अमान्य होगा क्योंकि cons
फ़ंक्शन को उम्मीद है कि उसका रिटर्न प्रकार सहसंयोजक होगा ।
हमारे यहाँ केवल दो विकल्प हैं) एक A
अपरिवर्तनीय बनाते हैं , कोवरियन के अच्छे, सहज उप-टाइपिंग गुण खो देते हैं, या ख) एक स्थानीय प्रकार के पैरामीटर को उस cons
विधि में जोड़ते हैं जो A
एक निचली सीमा के रूप में परिभाषित करता है :
def cons[B >: A](v: B): List[B]
यह अब मान्य है। आप कल्पना कर सकते हैं कि A
यह नीचे की ओर अलग है, लेकिन इसकी निचली सीमा के बाद से B
ऊपर की ओर अलग-अलग A
हो सकता A
है। इस पद्धति की घोषणा के साथ, हम A
सहसंयोजक हो सकते हैं और सब कुछ काम करता है।
ध्यान दें कि यह ट्रिक केवल तभी काम करती है जब हम एक ऐसे उदाहरण को वापस करते हैं List
जो कम-विशिष्ट प्रकार पर विशेष होता है B
। यदि आप List
परिवर्तनशील बनाने की कोशिश करते हैं , तो चीजें खत्म हो जाती हैं क्योंकि आप प्रकार के मूल्यों B
को एक चर के प्रकार को निर्दिष्ट करने की कोशिश कर रहे हैं A
, जो संकलक द्वारा अस्वीकृत है। जब भी आपके पास उत्परिवर्तन होता है, तो आपको कुछ प्रकार के एक म्यूटेटर की आवश्यकता होती है, जिसके लिए एक निश्चित प्रकार के एक विधि पैरामीटर की आवश्यकता होती है, जो (एक्सेसर के साथ) अव्यवस्था का अर्थ है। सहसंयोजक अपरिवर्तनीय डेटा के साथ काम करता है क्योंकि एकमात्र संभव संचालन एक सहायक है, जिसे एक सहसंयोजक रिटर्न प्रकार दिया जा सकता है।
var
सुलझनेval
योग्य नहीं है। यह वही कारण है कि स्केला के अपरिवर्तनीय संग्रह सहसंयोजक हैं, लेकिन उत्परिवर्तनीय नहीं हैं।