আমি জানিনা এই সমস্যার জন্য একটি নির্দিষ্ট শব্দ আছে কিনা, তবে এখানে তিনটি সাধারণ শ্রেণির সমাধান রয়েছে:
- গতিশীল প্রেরণের পক্ষে কংক্রিটের প্রকারগুলি এড়িয়ে চলুন
- টাইপ সীমাবদ্ধতায় স্থানধারক ধরণের পরামিতিগুলিকে অনুমতি দিন
- সম্পর্কিত ধরণের / ধরণের পরিবারগুলি ব্যবহার করে প্রকারের পরামিতিগুলি এড়ান
এবং অবশ্যই ডিফল্ট সমাধান: এই সমস্ত পরামিতিগুলি বানান রাখুন।
কংক্রিটের ধরণগুলি এড়িয়ে চলুন।
আপনি একটি Iterable
ইন্টারফেস হিসাবে এটি সংজ্ঞায়িত করেছেন:
interface <Element> Iterable<T: Iterator<Element>> {
getIterator(): T
}
এটি ইন্টারফেসের ব্যবহারকারীদের সর্বাধিক শক্তি দেয় কারণ তারা T
পুনরুক্তির সঠিক কংক্রিট ধরণের পায়। এটি একটি সংকলককে ইনলাইনিংয়ের মতো আরও অনুকূলিতকরণ প্রয়োগ করতেও সহায়তা করে।
তবে, যদি Iterator<E>
গতিশীলভাবে প্রেরণ করা ইন্টারফেস হয় তবে কংক্রিটের ধরণটি জানা জরুরী নয়। এটি উদাহরণস্বরূপ জাভা ব্যবহার করে এমন সমাধান। ইন্টারফেসটি তখন লেখা হবে:
interface Iterable<Element> {
getIterator(): Iterator<Element>
}
এর একটি আকর্ষণীয় প্রকরণটি হ'ল রাস্টের impl Trait
সিনট্যাক্স যা আপনাকে একটি বিমূর্ত রিটার্ন টাইপের সাহায্যে ফাংশনটি ঘোষণা করতে দেয় তবে কংক্রিটের ধরণটি কল সাইটে জানা যাবে (এইভাবে অপ্টিমাইজেশনের অনুমতি দেয়)। এটি একটি অন্তর্নিহিত ধরণের পরামিতিগুলির অনুরূপ আচরণ করে।
স্থানধারক ধরণের পরামিতিগুলির অনুমতি দিন।
Iterable
ইন্টারফেস, উপাদান টাইপ সম্পর্কে জানতে তাই এটি এই লিখতে সম্ভব হতে পারে প্রয়োজন নেই:
interface Iterable<T: Iterator<_>> {
getIterator(): T
}
যেখানে T: Iterator<_>
উপাদানটির ধরন নির্বিশেষে “টি কোনও পুনরুক্তি হয়” বাধাটি প্রকাশ করে। আরও কঠোরভাবে, আমরা এটিকে প্রকাশ করতে পারি: "কোনও ধরণের উপস্থিত রয়েছে Element
তাই এটি T
একটি Iterator<Element>
", এর জন্য কোনও কংক্রিটের প্রকারভেদ না জেনে Element
। এর অর্থ হ'ল টাইপ-এক্সপ্রেশনটি Iterator<_>
প্রকৃত ধরণের বর্ণনা দেয় না এবং কেবল টাইপ সীমাবদ্ধতা হিসাবে ব্যবহার করা যেতে পারে।
প্রকারের পরিবার / সম্পর্কিত ধরণের ব্যবহার করুন।
সি ++ তে যেমন কোনও টাইপের সদস্য থাকতে পারে। এটি সাধারণত স্ট্যান্ডার্ড লাইব্রেরি জুড়ে ব্যবহৃত হয়, যেমন std::vector::value_type
। এটি সত্যই সমস্ত পরিস্থিতিতে প্যারামিটার ধরণের সমস্যাটি সমাধান করে না, তবে যেহেতু একটি প্রকার অন্য ধরণের ক্ষেত্রে উল্লেখ করতে পারে তাই একক প্রকারের প্যারামিটার সম্পর্কিত ধরণের পুরো পরিবারকে বর্ণনা করতে পারে।
আসুন সংজ্ঞা দিন:
interface Iterator {
type ElementType
fn next(): ElementType
}
interface Iterable {
type IteratorType: Iterator
fn getIterator(): IteratorType
}
তারপর:
class Vec<Element> implement Iterable {
type IteratorType = VecIterator<Element>
fn getIterator(): IteratorType { ... }
}
class VecIterator<T> implements Iterator {
type ElementType = T
fn next(): ElementType { ... }
}
এটি দেখতে খুব নমনীয় মনে হচ্ছে তবে নোট করুন যে এটি ধরণের প্রতিবন্ধকতা প্রকাশ করা আরও কঠিন করে তুলতে পারে। যেমন লিখিত হিসাবে Iterable
কোনও পুনরাবৃত্ত উপাদান উপাদান প্রকার প্রয়োগ করে না এবং আমরা এর interface Iterator<T>
পরিবর্তে ঘোষণা করতে চাই । এবং আপনি এখন মোটামুটি জটিল ধরণের ক্যালকুলাস নিয়ে কাজ করছেন। দুর্ঘটনাক্রমে এ জাতীয় ধরণের সিস্টেমটিকে অনির্বাণযোগ্য করে তোলা খুব সহজ (বা এটি ইতিমধ্যে ইতিমধ্যে?)।
নোট করুন যে প্রকারের পরামিতিগুলির জন্য ডিফল্ট হিসাবে সম্পর্কিত প্রকারগুলি খুব সুবিধাজনক হতে পারে। উদাহরণস্বরূপ ধরে নিচ্ছি যে Iterable
ইন্টারফেসটির জন্য উপাদান টাইপের জন্য পৃথক ধরণের প্যারামিটারের প্রয়োজন হয় যা সাধারণত তবে পুনরাবৃত্তকারী উপাদান টাইপের মতো নয় এবং আমাদের কাছে স্থানধারক ধরণের পরামিতি রয়েছে, এটি বলা যেতে পারে:
interface Iterable<T: Iterator<_>, Element = T::Element> {
...
}
তবে এটি কেবল একটি ভাষা এরগনমিক্স বৈশিষ্ট্য এবং ভাষাটিকে আরও শক্তিশালী করে না।
প্রকার সিস্টেমগুলি কঠিন, তাই অন্যান্য ভাষায় কী করে এবং কী করে না সে সম্পর্কে একবার নজর দেওয়া ভাল।
উদাহরণস্বরূপ জং বইয়ের উন্নত বৈশিষ্ট্য অধ্যায়টি পড়া বিবেচনা করুন , যা সম্পর্কিত প্রকারের বিষয়ে আলোচনা করে। তবে মনে রাখবেন যে জেনেরিকের পরিবর্তে সম্পর্কিত ধরণের পক্ষে কিছু পয়েন্ট কেবল সেখানে প্রয়োগ হয় কারণ ভাষাটি সাবটাইপিংয়ের বৈশিষ্ট্য দেয় না এবং প্রতিটি বৈশিষ্ট্য কেবলমাত্র প্রতি টাইপটিতে একবারে প্রয়োগ করা যেতে পারে। অর্থাৎ মরিচা বৈশিষ্ট্যগুলি জাভা-জাতীয় ইন্টারফেস নয়।
অন্যান্য আকর্ষণীয় ধরণের সিস্টেমে হ্যাশেল বিভিন্ন ভাষা এক্সটেনশন সহ অন্তর্ভুক্ত। ওসিএএমএল মডিউল / ফান্টেক্টরগুলি হ'ল বস্তু বা প্যারামিটারাইজড প্রকারের সাথে সরাসরি মেশানো না রেখে টাইপ পরিবারের তুলনামূলকভাবে সরল সংস্করণ। জাভা তার টাইপ সিস্টেমে সীমাবদ্ধতার জন্য উল্লেখযোগ্য, উদাহরণস্বরূপ মুছে ফেলার মতো জেনেরিক এবং মান ধরণের চেয়ে বেশি জেনেরিক। সি # খুব জাভা-এর মতো তবে বর্ধিত বাস্তবায়ন জটিলতায় এই সীমাবদ্ধতাগুলির বেশিরভাগটিকে এড়াতে পরিচালনা করে। স্কালা জাভা প্ল্যাটফর্মের শীর্ষে হাস্কেল-স্টাইলের টাইপক্ল্যাসগুলির সাথে সি # স্টাইল জেনেরিকগুলিকে একীভূত করার চেষ্টা করে। সি ++ এর ছদ্মবেশী সহজ টেম্পলেটগুলি ভালভাবে অধ্যয়ন করা হয়েছে তবে বেশিরভাগ জেনেরিক প্রয়োগগুলির মতো নয়।
সাধারণত কোন নিদর্শনগুলি ব্যবহৃত হয় তা দেখার জন্য এই ভাষার স্ট্যান্ডার্ড লাইব্রেরিগুলি (বিশেষত স্ট্যান্ডার্ড লাইব্রেরি সংগ্রহগুলি তালিকাগুলি বা হ্যাশ টেবিলগুলি) দেখার জন্য এটিও মূল্যবান। উদাহরণস্বরূপ, সি ++ এর বিভিন্ন পুনরুক্তিযোগ্য ক্ষমতাগুলির একটি জটিল সিস্টেম রয়েছে এবং স্কালা বৈশিষ্ট্য হিসাবে সূক্ষ্ম-দানা সংগ্রহের ক্ষমতা এনকোড করে। জাভা স্ট্যান্ডার্ড লাইব্রেরি ইন্টারফেসগুলি কখনও কখনও উদ্বুদ্ধ হয় না, যেমন Iterator#remove()
, তবে একজাতীয় ধরণের (যেমন Map.Entry
) হিসাবে নেস্টেড ক্লাস ব্যবহার করতে পারে ।