সাধারণভাবে, একটি কোভেরিয়েন্ট টাইপ প্যারামিটার এমন একটি যা ক্লাসটি সাব-টাইপ করা হয়েছে (বিকল্পভাবে, সাব টাইপিংয়ের সাথে পৃথক হয়, তাই "সহ-উপসর্গ) থাকে down আরও দৃ concrete়ভাবে:
trait List[+A]
List[Int]এর একটি উপপ্রকার List[AnyVal]কারণ Intএটি একটি উপপ্রকার AnyVal। এর অর্থ হ'ল আপনি List[Int]যখন কোনও ধরণের মান List[AnyVal]আশা করা যায় তার একটি উদাহরণ সরবরাহ করতে পারেন । জেনেরিকদের কাজ করার জন্য এটি সত্যই একটি স্বজ্ঞাত উপায়, তবে এটি মিলে যায় এমন ডেটা উপস্থিতি ব্যবহার করার সময় এটি নিরবচ্ছিন্ন (টাইপ সিস্টেমটি বিরতি দেয়) হয়ে যায়। এজন্য জেনারিকস জাভাতে আক্রমণকারী। জাভা অ্যারেগুলি ব্যবহার করে অস্পষ্টতার সংক্ষিপ্ত উদাহরণ (যা ভ্রান্তভাবে সহকর্মী হয়):
Object[] arr = new Integer[1];
arr[0] = "Hello, there!";
আমরা সবেমাত্র টাইপের Stringএকটি অ্যারে টাইপের মান নির্ধারণ করেছি Integer[]। যে কারণে স্পষ্ট হওয়া উচিত, এটি খারাপ সংবাদ। জাভা টাইপ সিস্টেম আসলে এটি সংকলন সময়ে অনুমতি দেয়। জেভিএম ArrayStoreExceptionরানটাইমটিতে "সহায়তা করে" একটি নিক্ষেপ করবে । স্কালার টাইপ সিস্টেমটি এই সমস্যাটিকে প্রতিরোধ করে কারণ Arrayক্লাসে টাইপ পরামিতি অবিস্মরণীয় (ঘোষণার [A]পরিবর্তে হয় [+A])।
নোট করুন যে আরও একটি ধরণের বৈকল্পিক রয়েছে যা বিপরীত হিসাবে পরিচিত । এটি অত্যন্ত গুরুত্বপূর্ণ কারণ এটি ব্যাখ্যা করে যে কেন সম্প্রদায় কিছু সমস্যা সৃষ্টি করতে পারে। Contravariance আক্ষরিক সহভেদাংক বিপরীত: পরামিতি পরিবর্তন হওয়ার সম্ভাবনা রয়েছে উর্ধ্বগামী subtyping সঙ্গে। এটি আংশিকভাবে অনেক কম সাধারণ কারণ এটি এতটা আন্তঃজ্ঞানযুক্ত, যদিও এটির একটি খুব গুরুত্বপূর্ণ প্রয়োগ রয়েছে: ফাংশন functions
trait Function1[-P, +R] {
def apply(p: P): R
}
টাইপ প্যারামিটারে " - " ভেরিয়েন্ট টীকাটি লক্ষ্য করুন P। একটি সম্পূর্ণ উপায়ে যে হিসাবে এই ঘোষণা Function1মধ্যে contravariant হয় Pএবং covariant R। সুতরাং, আমরা নিম্নলিখিত অক্ষরেখা পেতে পারি:
T1' <: T1
T2 <: T2'
---------------------------------------- S-Fun
Function1[T1, T2] <: Function1[T1', T2']
লক্ষ করুন যে, T1'একটি উপপ্রকার (অথবা একই ধরনের) হবে T1, যেহেতু এটি জন্য বিপরীত T2এবং T2'। ইংরাজীতে, এটি নিম্নলিখিত হিসাবে পড়া যেতে পারে:
একটি ফাংশন একটি অন্য ফাংশন একটি উপপ্রকার হয় বি যদি এর প্যারামিটার প্রকার একজন এর প্যারামিটার প্রকার একটি supertype হয় বি যখন এর রিটার্ন টাইপ একজন ফেরত ধরনের উপপ্রকার হয় বি ।
এই নিয়মের কারণ পাঠকের কাছে অনুশীলন হিসাবে ছেড়ে দেওয়া হয়েছে (ইঙ্গিত: ফাংশনগুলি সাব টাইপ করা হওয়ায় বিভিন্ন বিষয় সম্পর্কে চিন্তা করুন, যেমন উপরে থেকে আমার অ্যারের উদাহরণ হিসাবে)।
আপনার নতুন-সহ-ধারণা ও বৈপরীত্য সম্পর্কিত জ্ঞানের সাথে, নীচের উদাহরণটি কেন সংকলন করবে না তা আপনি দেখতে সক্ষম হবেন:
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থেকে সম্মানের সাথে wardর্ধ্বমুখী পরিবর্তিত করতে সক্ষম A। এই পদ্ধতির ঘোষণার সাথে আমরা Aসমবায় হতে পারি এবং সমস্ত কিছু কার্যকর হয়।
লক্ষ্য করুন এই কৌতুক শুধুমাত্র কাজ করে যদি আমরা একটি দৃষ্টান্ত ফেরত Listযা কম-নির্দিষ্ট ধরনের উপর বিশেষজ্ঞ B। আপনি যদি Listপরিবর্তনীয় করার চেষ্টা করেন তবে জিনিসগুলি ভেঙে যায় যেহেতু আপনি টাইপের মানকে টাইপের Bএকটি ভেরিয়েবলের জন্য নির্ধারণের চেষ্টা শেষ করেন A, যা সংকলক দ্বারা অনুমোদিত নয়। আপনি যখনই পরিবর্তন আনতে পারেন, আপনার কোনও ধরণের মিউটেটর থাকা দরকার, যার জন্য নির্দিষ্ট ধরণের একটি পদ্ধতি প্যারামিটার প্রয়োজন হয়, যা (একসেসরের সাথে একসাথে) অদম্যতা বোঝায়। কোভারিয়েন্স অপরিবর্তনীয় ডেটা নিয়ে কাজ করে যেহেতু একমাত্র সম্ভাব্য অপারেশনটি একজন অ্যাক্সেসর, যা একটি সমবায় রিটার্ন টাইপ দেওয়া যেতে পারে।
varস্থিরযোগ্য যদিওvalনেই। স্ক্যালালের অপরিবর্তনীয় সংগ্রহগুলি সমবায় এবং একইভাবে পরিবর্তনীয় সংগ্রহগুলি একই কারণ নয়।