উত্তর:
আমি আওয়াজে আমার কন্ঠ যুক্ত করব এবং বিষয়গুলি পরিষ্কার করার জন্য এক ছুরিকাঘাত করব:
List<Person> foo = new List<Person>();
এবং তারপরে সংকলক আপনাকে Person
তালিকায় নেই এমন জিনিসগুলি স্থাপন থেকে বাধা দেবে ।
পর্দার আড়ালে সি # সংকলকটি কেবল List<Person>
নেট নেট ডিএল ফাইলের মধ্যে রাখছে, তবে রানটাইমের সময় জেআইটি সংকলক গিয়ে কোডের একটি নতুন সেট তৈরি করে, যেন আপনি কেবল লোক ধারণের জন্য একটি বিশেষ তালিকা শ্রেণি লিখেছিলেন - এরকম কিছু ListOfPerson
।
এর সুবিধা হ'ল এটি এটিকে সত্যই দ্রুত করে তোলে। এখানে কোনও ingালাই বা অন্য কোনও জিনিস নেই, এবং যেহেতু ডেলিতে তথ্য রয়েছে যা এটি একটি তালিকা Person
, অন্য কোড যা প্রতিফলন ব্যবহারের পরে এটি দেখায় তা বলতে পারে যে এতে Person
অবজেক্ট রয়েছে (যাতে আপনি ইন্টেলিজেন্স পেয়ে থাকেন)।
এর নেতিবাচক দিকটি হ'ল পুরাতন সি # 1.0 এবং 1.1 কোড (তারা জেনেরিক যুক্ত করার আগে) এই নতুনটি বুঝতে পারে না List<something>
, সুতরাং List
তাদের সাথে ইন্টারঅ্যাক্ট করতে আপনাকে জিনিসগুলি ম্যানুয়ালি ফিরিয়ে পুরানোতে রূপান্তর করতে হবে। এটি কোনও সমস্যার বড় নয়, কারণ সি # 2.0 বাইনারি কোড পিছনের দিকে সামঞ্জস্যপূর্ণ নয়। আপনি যদি কিছু পুরানো সি # 1.0 / 1.1 কোডটি সি # 2.0 তে আপগ্রেড করেন তবে একমাত্র সময়টি কখনই ঘটবে
ArrayList<Person> foo = new ArrayList<Person>();
পৃষ্ঠতলে এটি দেখতে একইরকম এবং এটি সাজানো। সংকলকটি Person
তালিকায় নেই এমন জিনিসগুলি রাখার থেকে আপনাকে বাধা দেবে ।
পার্থক্য হ'ল পর্দার আড়ালে কী ঘটে। সি # এর বিপরীতে, জাভা যায় না এবং একটি বিশেষ নির্মাণ করে না ListOfPerson
- এটি কেবল প্লেইন পুরাতন ব্যবহার করে ArrayList
যা সর্বদা জাভাতে রয়েছে। আপনি জিনিসগুলি অ্যারে থেকে বেরিয়ে এলে, Person p = (Person)foo.get(1);
এখনও সাধারণ কাস্টিং-ডান্স করতে হবে। সংকলকটি আপনাকে কী-টিপুনগুলি সংরক্ষণ করছে, তবে গতি হিট / ingালাই এখনও সর্বদা যেমন ছিল তেমনই ব্যয় করে।
লোকেরা যখন "টাইপ ইরেজোর" উল্লেখ করে তারা এই বিষয়ে কথা বলছে। সংকলকটি আপনার জন্য কাস্টগুলি সন্নিবেশ করিয়েছে এবং তারপরে এটি সত্য নয় যে এটি কেবল একটি তালিকা Person
নয়Object
এই পদ্ধতির সুবিধাটি হ'ল সেই পুরানো কোড যা জেনেরিকগুলি বোঝে না সেগুলির কোনও যত্ন নেওয়া উচিত নয়। এটি এখনও আগের ArrayList
মতো একইরকম আচরণ করে । এটি জাভা বিশ্বে আরও গুরুত্বপূর্ণ কারণ তারা জেনারিকের সাথে জাভা 5 ব্যবহার করে সংকলন কোডটি সমর্থন করতে চেয়েছিল এবং এটি পুরানো 1.4 বা পূর্ববর্তী জেভিএম-এর উপর চালানো হয়েছে, যা মাইক্রোসফ্ট ইচ্ছাকৃতভাবে বিরক্ত না করার সিদ্ধান্ত নিয়েছে।
ক্ষতিটি হ'ল আমি আগে উল্লিখিত গতি হিট এবং এছাড়াও কারণ কোনও ListOfPerson
সিউডো-শ্রেণি বা .class ফাইলগুলিতে যাওয়ার মতো কোনও কিছু নেই বলে পরে কোডটি দেখায় এমন কোড (প্রতিফলন সহ, অথবা আপনি যদি এটি অন্য সংগ্রহ থেকে বের করেন) যেখানে এটি রূপান্তরিত হয়েছে Object
বা Person
অন্যদিকে ) এটি কোনওভাবেই বলতে পারে না যে এটি কেবলমাত্র অন্য কোনও অ্যারে তালিকা নয় কেবল একটি তালিকা রয়েছে।
std::list<Person>* foo = new std::list<Person>();
এটি সি # এবং জাভা জেনেরিকগুলির মতো দেখায় এবং এটি আপনার করা উচিত বলে মনে করে তা করবে তবে পর্দার আড়ালে বিভিন্ন জিনিস ঘটছে।
এটি সি # জেনেরিকগুলির মধ্যে সবচেয়ে বেশি সাধারণ কারণ এটি pseudo-classes
জাভা যেমন প্রকারের তথ্য ফেলে দেওয়ার চেয়ে বিশেষ তৈরি করে তবে এটি মাছের সম্পূর্ণ ভিন্ন কেতলি।
সি # এবং জাভা উভয়ই আউটপুট উত্পাদন করে যা ভার্চুয়াল মেশিনের জন্য ডিজাইন করা হয়েছে। আপনি যদি কিছু কোড লিখে থাকেন যার একটি Person
ক্লাস রয়েছে, উভয় ক্ষেত্রেই একটি Person
শ্রেণীর সম্পর্কে কিছু তথ্য .dll বা .class ফাইলের মধ্যে যাবে এবং জেভিএম / সিএলআর এটি দিয়ে স্টাফ করবে।
সি ++ কাঁচা x86 বাইনারি কোড উত্পাদন করে। সবকিছুই কোনও বস্তু নয় এবং কোনও অন্তর্নিহিত ভার্চুয়াল মেশিন নেই যা একটি Person
শ্রেণীর সম্পর্কে জানতে হবে । এখানে বক্সিং বা আনবক্সিং নেই, এবং ফাংশনগুলির ক্লাসে বা কোনও কিছুর অন্তর্ভুক্ত নয়।
এ কারণে, সি ++ সংকলক টেম্পলেটগুলির সাথে আপনি কী করতে পারেন তার উপর কোনও বিধিনিষেধ রাখে না - মূলত আপনি যে কোনও কোড ম্যানুয়ালি লিখতে পারেন, আপনি আপনার জন্য লেখার জন্য টেমপ্লেট পেতে পারেন।
সর্বাধিক সুস্পষ্ট উদাহরণ জিনিস যুক্ত করা হয়:
সি # এবং জাভাতে জেনেরিক সিস্টেমটি কোনও শ্রেণীর জন্য কী কী পদ্ধতি উপলব্ধ তা জেনে রাখা দরকার এবং এটি এটিকে ভার্চুয়াল মেশিনে পৌঁছে দেওয়া দরকার। এটি বলার একমাত্র উপায় হ'ল হয় প্রকৃত শ্রেণিতে হার্ড কোডিং করা বা ইন্টারফেস ব্যবহার করা। উদাহরণ স্বরূপ:
string addNames<T>( T first, T second ) { return first.Name() + second.Name(); }
এই কোডটি সি # বা জাভাতে সংকলন করবে না, কারণ এটি জানে না যে টাইপটি T
আসলে নাম () নামে একটি পদ্ধতি সরবরাহ করে। আপনাকে এটি বলতে হবে - সি # তে এর মতো:
interface IHasName{ string Name(); };
string addNames<T>( T first, T second ) where T : IHasName { .... }
এবং তারপরে আপনাকে নিশ্চিত করতে হবে যেগুলি আপনি অ্যাডনামগুলিতে পাস করেছেন সেগুলি IHasName ইন্টারফেস এবং আরও কিছু প্রয়োগ করে। জাভা সিনট্যাক্স পৃথক ( <T extends IHasName>
), তবে এটি একই সমস্যায় ভোগে।
এই সমস্যার জন্য 'ক্লাসিক' কেস একটি ফাংশন লেখার চেষ্টা করছে যা এটি করে
string addNames<T>( T first, T second ) { return first + second; }
আপনি আসলে এই কোডটি লিখতে পারবেন না কারণ এতে কোনও পদ্ধতির সাথে ইন্টারফেস ঘোষণা করার কোনও উপায় নেই +
। আপনি ব্যর্থ.
সি ++ এগুলির কোনও সমস্যা থেকে ভোগেন। সংকলকটি কোনও ভিএম এর মধ্যে প্রকারগুলি প্রবাহের বিষয়ে চিন্তা করে না - যদি আপনার উভয় বস্তুর একটি .Name () ফাংশন থাকে, তবে এটি সংকলন করবে। যদি তারা না করে তবে তা হবে না। সহজ।
তাই সেখানে যদি আপনি এটি আছে :-)
int addNames<T>( T first, T second ) { return first + second; }
আপনি C # তে লিখতে পারবেন না এমন বিবৃতিতে আমি আপত্তি জানাই । জেনেরিক টাইপটি একটি ইন্টারফেসের পরিবর্তে কোনও শ্রেণিতে সীমাবদ্ধ হতে পারে এবং এতে +
অপারেটরের সাথে কোনও শ্রেণি ঘোষণার উপায় রয়েছে ।
সি ++ খুব কমই "জেনেরিক্স" পরিভাষা ব্যবহার করে। পরিবর্তে, "টেমপ্লেট" শব্দটি ব্যবহৃত হয়েছে এবং আরও সঠিক। টেমপ্লেটগুলি জেনেরিক নকশা অর্জনের জন্য একটি কৌশল বর্ণনা করে ।
সি ++ টেমপ্লেট দুটি মূল কারণে সি # এবং জাভা উভয়ই প্রয়োগ করে তার থেকে খুব আলাদা। প্রথম কারণটি হ'ল সি ++ টেমপ্লেটগুলি কেবল সংকলন-টাইম ধরণের আর্গুমেন্টকে অনুমতি দেয় না তবে সংকলন-কাল কনস্ট-মান যুক্তিগুলিও দেয়: টেমপ্লেটগুলি পূর্ণসংখ্যা বা এমনকি ফাংশন স্বাক্ষর হিসাবেও দেওয়া যেতে পারে। এর অর্থ হ'ল সংকলনের সময় আপনি বেশ কিছু মজার স্টাফ করতে পারেন, যেমন গণনা:
template <unsigned int N>
struct product {
static unsigned int const VALUE = N * product<N - 1>::VALUE;
};
template <>
struct product<1> {
static unsigned int const VALUE = 1;
};
// Usage:
unsigned int const p5 = product<5>::VALUE;
এই কোডটি সি ++ টেম্পলেটগুলির অন্যান্য স্বতন্ত্র বৈশিষ্ট্যও ব্যবহার করে, যেমন টেমপ্লেট বিশেষীকরণ। কোডটি একটি শ্রেণির টেমপ্লেট সংজ্ঞায়িত করে, product
এতে একটি মান যুক্তি রয়েছে has এটি সেই টেম্পলেটটির জন্য একটি বিশেষত্বও সংজ্ঞায়িত করে যা যখনই যুক্তি 1 টির জন্য মূল্যায়ন করে তখন এটি ব্যবহৃত হয় This আমি বিশ্বাস করি যে এটি প্রথম আন্দ্রেই আলেকজান্দ্রেস্কু আবিষ্কার করেছিলেন ।
টেমপ্লেট বিশেষীকরণ সি ++ এর জন্য গুরুত্বপূর্ণ কারণ এটি ডেটা স্ট্রাকচারের কাঠামোগত পার্থক্যের জন্য অনুমতি দেয়। সামগ্রিকভাবে টেমপ্লেটগুলি বিভিন্ন ধরণের ইন্টারফেসকে একত্রিত করার একটি মাধ্যম। তবে এটি আকাঙ্খিত হলেও বাস্তবায়নের অভ্যন্তরে সমস্ত ধরণের সমানভাবে আচরণ করা যায় না। সি ++ টেমপ্লেটগুলি এটি অ্যাকাউন্টে নেয়। এটি ভার্চুয়াল পদ্ধতিগুলির ওভাররাইডিংয়ের সাথে ইন্টারফেস এবং প্রয়োগের মধ্যে অনেকটাই একই পার্থক্য।
সি ++ টেমপ্লেটগুলি এর অ্যালগরিদমিক প্রোগ্রামিং দৃষ্টান্তের জন্য প্রয়োজনীয়। উদাহরণস্বরূপ, ধারকগুলির জন্য প্রায় সমস্ত অ্যালগরিদমগুলি এমন ফাংশন হিসাবে সংজ্ঞায়িত করা হয় যা ধারক প্রকারটিকে একটি টেম্পলেট প্রকার হিসাবে গ্রহণ করে এবং তাদের সাথে অভিন্ন আচরণ করে। আসলে, এটি একেবারেই ঠিক নয়: সি ++ পাত্রে নয় বরং ধারকগুলির শুরুতে এবং পেছনের দিকে নির্দেশ করে দুটি পুনরুক্তি দ্বারা সংজ্ঞায়িত রেঞ্জগুলিতে কাজ করে না । সুতরাং, সম্পূর্ণ সামগ্রীটি পুনরাবৃত্তিকারীদের দ্বারা পরিবেশন করা হয়: শুরু <= উপাদান <শেষ।
পাত্রে পরিবর্তে পুনরায় ব্যবহার করা কার্যকর কারণ এটি পুরোপুরি পরিবর্তে কোনও ধারক অংশে কাজ করতে দেয়।
C ++ এর আর একটি স্বতন্ত্র বৈশিষ্ট্য হ'ল শ্রেণীর টেম্পলেটগুলির জন্য আংশিক বিশেষজ্ঞের সম্ভাবনা । এটি কিছুটা হাস্কেল এবং অন্যান্য কার্যকরী ভাষায় যুক্তির সাথে প্যাটার্ন মিলের সাথে সম্পর্কিত। উদাহরণস্বরূপ, আসুন একটি শ্রেণি বিবেচনা করুন যা উপাদানগুলি সঞ্চয় করে:
template <typename T>
class Store { … }; // (1)
এটি যে কোনও উপাদান ধরণের জন্য কাজ করে। তবে আসুন আমরা বলি যে আমরা কিছু বিশেষ কৌশল প্রয়োগ করে অন্যান্য ধরণের চেয়ে পয়েন্টারগুলিকে আরও দক্ষতার সাথে সঞ্চয় করতে পারি। আমরা সমস্ত পয়েন্টার ধরণের জন্য আংশিকভাবে বিশেষায়িত করে এটি করতে পারি :
template <typename T>
class Store<T*> { … }; // (2)
এখন, যখনই আমরা এক ধরণের জন্য একটি ধারক টেম্পলেট উপস্থাপন করি, উপযুক্ত সংজ্ঞা ব্যবহৃত হয়:
Store<int> x; // Uses (1)
Store<int*> y; // Uses (2)
Store<string**> z; // Uses (2), with T = string*.
অ্যান্ডারস হেজলসবার্গ নিজেই এখানে পার্থক্য বর্ণনা করেছেন "জেনারিকস ইন সি #, জাভা এবং সি ++ "।
ইতিমধ্যেই ভাল উত্তর অনেক আছে কি পার্থক্য আছে, তাই আমাকে একটি কিছুটা ভিন্ন আঙ্গিক দিতে দিন যোগ কেন ।
যেমনটি আগেই ব্যাখ্যা করা হয়েছিল, মূল পার্থক্যটি টাইপ ইরেজর , অর্থাৎ জাভা সংকলক জেনেরিক প্রকারগুলি মুছে দেয় এবং এগুলি উত্পন্ন বাইকোডে শেষ হয় না। তবে, প্রশ্নটি হল: কেউ কেন এমন করবে? এটা বোঝা যায় না! নাকি তা করে?
ঠিক আছে, বিকল্প কি? আপনি ভাষায় জেনেরিক্স বাস্তবায়ন না থাকে, তাহলে যেখানে না আপনি তাদের বাস্তবায়ন? এবং উত্তরটি হ'ল ভার্চুয়াল মেশিনে। যা পিছনের দিকে সামঞ্জস্যতা ভঙ্গ করে।
অন্যদিকে মুছে ফেলা টাইপ আপনাকে জেনেরিক ক্লায়েন্টগুলিকে নন-জেনেরিক লাইব্রেরির সাথে মিশ্রিত করতে দেয়। অন্য কথায়: জাভা 5 তে সংকলিত কোডটি এখনও জাভা 1.4 এ স্থাপন করা যেতে পারে।
মাইক্রোসফ্ট অবশ্য জেনেরিকের জন্য সামনের সামঞ্জস্যতা ভেঙে ফেলার সিদ্ধান্ত নিয়েছে। এজন্য। নেট জেনেরিক্স জাভা জেনেরিক্সের চেয়ে "ভাল"।
অবশ্যই, সান বোকা বা কাপুরুষ নয়। তারা "ছত্রভঙ্গ" হওয়ার কারণটি ছিল যে জেনারিকগুলি প্রবর্তন করার সময় জাভাটি নেট থেকে অনেক বেশি বয়স্ক এবং বেশি বিস্তৃত ছিল। (এগুলি উভয় জগতে মোটামুটি একই সময়ে প্রবর্তিত হয়েছিল।) পিছনের দিকে সামঞ্জস্যতা ভঙ্গ করা একটি বিশাল ব্যথা হত।
আরও একটি উপায় রাখুন: জাভাতে জেনেরিক্স ভাষার একটি অংশ (যার অর্থ তারা কেবল জাভাতে প্রয়োগ হয়, অন্য ভাষায় নয়), নেট এ তারা ভার্চুয়াল মেশিনের অংশ (যার অর্থ তারা সমস্ত ভাষায় প্রয়োগ করে , না কেবল সি # এবং ভিজ্যুয়াল বেসিক N নেট)।
লিনকিউ, ল্যাম্বডা এক্সপ্রেশন, স্থানীয় ভেরিয়েবল টাইপ অনুমান, বেনামি প্রকার এবং অভিব্যক্তি গাছের মতো .NET বৈশিষ্ট্যগুলির সাথে এটির তুলনা করুন: এগুলি সমস্ত ভাষার বৈশিষ্ট্য। এই কারণেই ভিবি.এনইটি এবং সি # এর মধ্যে সূক্ষ্ম পার্থক্য রয়েছে: যদি এই বৈশিষ্ট্যগুলি ভিএম এর অংশ হয়, তবে সমস্ত ভাষায় সেগুলি একই হবে । তবে সিএলআর পরিবর্তিত হয়নি: নেট .২.০ তে যেমন ছিল নেট SP.৩ এসপি 1 তে এটি এখনও একই। আপনি একটি সি # প্রোগ্রাম সংকলন করতে পারেন যা .NET 3.5 সংকলক সহ লিনকিউ ব্যবহার করে এবং এটি নেট .০.০.০ এ চালিত করুন, আপনি যদি কোনও নেট নেট ৩.৫ লাইব্রেরি ব্যবহার না করেন। এটি জেনেরিকস এবং .NET 1.1 এর সাথে কাজ করবে না , তবে এটি জাভা এবং জাভা 1.4 এর সাথে কাজ করবে ।
ArrayList<T>
একটি (লুকানো) স্ট্যাটিক Class<T>
ক্ষেত্র সহ একটি নতুন অভ্যন্তরীণ নামযুক্ত প্রকার হিসাবে নির্গত হতে পারে । যতক্ষণ না জেনেরিক লিবের নতুন সংস্করণটি 1.5+ বাইট কোড সহ স্থাপন করা হয়েছে ততক্ষণ এটি 1.4- জেভিএমগুলিতে চালাতে সক্ষম হবে।
আমার আগের পোস্টিং অনুসরণ করুন।
টেমপ্লেটগুলি আইডিই ব্যবহার না করেই, ইন্টেলিজেন্সে সি ++ এত অস্বাভাবিকভাবে ব্যর্থ হওয়ার একটি প্রধান কারণ। টেমপ্লেট বিশেষায়নের কারণে আইডিই কখনই নিশ্চিত হতে পারে না যে কোনও প্রদত্ত সদস্যের উপস্থিতি রয়েছে কি না। বিবেচনা:
template <typename T>
struct X {
void foo() { }
};
template <>
struct X<int> { };
typedef int my_int_type;
X<my_int_type> a;
a.|
এখন, কার্সারটি নির্দেশিত অবস্থানে রয়েছে এবং আইডিইর পক্ষে সদস্যরা a
আছে কিনা, এবং কী, সে সময়ে এটি বলা শক্ত । অন্যান্য ভাষার জন্য পার্সিং সোজা হবে তবে সি ++ এর জন্য আগেই বেশ কিছুটা মূল্যায়ন করা দরকার।
এটা খুব খারাপ হচ্ছে. my_int_type
শ্রেণিক টেম্পলেটটির মধ্যেও যদি সংজ্ঞায়িত করা হয়? এখন এর ধরণটি অন্য ধরণের আর্গুমেন্টের উপর নির্ভর করবে। এবং এখানে, এমনকি সংকলকগুলি ব্যর্থ হয়।
template <typename T>
struct Y {
typedef T my_type;
};
X<Y<int>::my_type> b;
কিছুটা চিন্তাভাবনা করার পরে, একজন প্রোগ্রামার এই সিদ্ধান্তে নেমে আসবে যে এই কোডটি উপরের মতই: Y<int>::my_type
সমাধান করে int
, তাই b
ঠিক একই ধরণের হওয়া উচিত , তাই a
না?
ভুল। সংকলক যেখানে এই বিবৃতিটি সমাধান করার চেষ্টা করে, বাস্তবে এটি Y<int>::my_type
এখনও জানে না! সুতরাং, এটি জানেন না যে এটি একটি প্রকার। এটি অন্য কোনও কিছু হতে পারে, যেমন সদস্য ফাংশন বা ক্ষেত্র। এটি অস্পষ্টতার জন্ম দিতে পারে (যদিও বর্তমান ক্ষেত্রে তা নয়), তাই সংকলক ব্যর্থ হয়। আমাদের এটি স্পষ্টভাবে বলতে হবে যে আমরা একটি প্রকারের নাম উল্লেখ করি:
X<typename Y<int>::my_type> b;
এখন, কোড সংকলন। এই পরিস্থিতি থেকে কীভাবে অস্পষ্টতা দেখা দেয় তা দেখতে নীচের কোডটি বিবেচনা করুন:
Y<int>::my_type(123);
এই কোড স্টেটমেন্টটি পুরোপুরি বৈধ এবং সি ++ কে ফাংশন কলটি কার্যকর করতে বলে Y<int>::my_type
। তবে, যদি my_type
কোনও ফাংশন না হয়ে বরং কোনও প্রকারের হয় তবে এই বিবৃতিটি বৈধ হবে এবং একটি বিশেষ কাস্ট (ফাংশন-শৈলীর castালাই) সঞ্চালিত হবে যা প্রায়শই নির্মাণকারীর অনুরোধ। সংকলকটি আমাদের বলতে কী বলতে পারে তা বলতে পারে না তাই আমাদের এখানে বিভ্রান্ত করতে হবে।
জাভা এবং সি # উভয়ই তাদের প্রথম ভাষা প্রকাশের পরে জেনেরিকগুলি চালু করেছিল। যাইহোক, জেনেরিকগুলি চালু করার সময় মূল পাঠাগারগুলি কীভাবে পরিবর্তিত হয়েছিল তার মধ্যে পার্থক্য রয়েছে। সি # এর জেনেরিকগুলি কেবল যাদু সংকলনকারী নয় এবং অতএব বিদ্যমান সামঞ্জস্যতা পিছনে সামঞ্জস্যতা না ভেঙে জেনারেট করা সম্ভব ছিল না ।
উদাহরণস্বরূপ, জাভাতে বিদ্যমান সংগ্রহ ফ্রেমওয়ার্ক সম্পূর্ণ জেনারাইজড হয়েছিল । জাভা সংগ্রহের ক্লাসগুলির জেনেরিক এবং উত্তরাধিকার নন-জেনেরিক সংস্করণ উভয়ই নেই। কিছু উপায়ে এটি অনেক বেশি পরিষ্কার - আপনার যদি সি # তে কোনও সংগ্রহের প্রয়োজন হয় তবে অ-জেনেরিক সংস্করণটি গ্রহণের খুব কম কারণ থাকতে পারে, তবে এই উত্তরাধিকারের শ্রেণিগুলি স্থানে রয়েছে, ল্যান্ডস্কেপটি বিশৃঙ্খলাবদ্ধ করে তোলে।
আর একটি উল্লেখযোগ্য পার্থক্য হ'ল জাভা এবং সি # তে এনাম ক্লাস। জাভার এনামের এই কিছুটা সংকটজনক সংজ্ঞা রয়েছে:
// java.lang.Enum Definition in Java
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
(অ্যাঞ্জেলিকা ল্যাঙ্গারের খুব স্পষ্ট ব্যাখ্যা দেখুন কেন এটি ঠিক ঠিক ।
// Parsing String to Enum in Java
Colour colour = Colour.valueOf("RED");
এটি সি # এর সংস্করণের সাথে তুলনা করুন:
// Parsing String to Enum in C#
Colour colour = (Colour)Enum.Parse(typeof(Colour), "RED");
ভাষাটিতে জেনেরিকের পরিচয় হওয়ার আগে এনাম ইতিমধ্যে সি # তে বিদ্যমান ছিল বলে বিদ্যমান কোডটি না ভেঙে সংজ্ঞাটি পরিবর্তন করতে পারে না। সুতরাং, সংগ্রহগুলির মতো এটিও এই উত্তরাধিকারের রাজ্যের মূল গ্রন্থাগারে রয়েছে।
ArrayList
করার প্রয়োজনের কোনও কারণ নেই List<T>
। আসল বিষয়টি হ'ল, যদি সোর্স কোডে কোনও শ্রেণি উপস্থিত হত কারণ ArrayList<T>
এটি আইএল কোডে একটি পৃথক সংকলক উত্পন্ন শ্রেণীর নাম হয়ে উঠবে, তাই কোনও নাম বিরোধ নেই happen
11 মাস দেরীতে, তবে আমি মনে করি এই প্রশ্নটি কিছু জাভা ওয়াইল্ডকার্ড স্টাফের জন্য প্রস্তুত।
এটি জাভার একটি সিনট্যাক্টিকাল বৈশিষ্ট্য। ধরুন আপনার একটি পদ্ধতি রয়েছে:
public <T> void Foo(Collection<T> thing)
এবং ধরুন আপনার মেথড বডি তে টি টাইপ করার দরকার নেই। আপনি একটি নাম টি ঘোষণা করছেন এবং তারপরে কেবল একবার এটি ব্যবহার করছেন, তবে এর জন্য আপনার নাম কেন ভাবা উচিত? পরিবর্তে, আপনি লিখতে পারেন:
public void Foo(Collection<?> thing)
প্রশ্ন-চিহ্নটি সংকলকটিকে এই ভঙ্গিতে জিজ্ঞাসা করে যে আপনি একটি সাধারণ নামযুক্ত টাইপ পরামিতি ঘোষণা করেছেন যা কেবলমাত্র সেই জায়গায় একবার উপস্থিত হওয়া প্রয়োজন।
ওয়াইল্ডকার্ডগুলির সাথে আপনার করার মতো কিছুই নেই যা আপনি একটি নামের ধরণের পরামিতি (যা এই জিনিসগুলি সর্বদা সি ++ এবং সি # তে করা হয়) দিয়েও করতে পারবেন না।
class Foo<T extends List<?>>
এবং ব্যবহার করুন Foo<StringList>
তবে সি # তে আপনাকে সেই অতিরিক্ত ধরণের পরামিতি যুক্ত করতে হবে: class Foo<T, T2> where T : IList<T2>
এবং ক্লাঙ্কিটি ব্যবহার করতে হবে Foo<StringList, String>
।
উইকিপিডিয়ায় জাভা / সি # জেনেরিকস এবং জাভা জেনেরিকস / সি ++ টেম্পলেটগুলির সাথে তুলনা করার জন্য দুর্দান্ত লেখাগুলি রয়েছে । জেনেরিক্স মূল নিবন্ধ একটু বিশৃঙ্খল বলে মনে হয় কিন্তু তা কিছু ভাল তথ্য আছে।
সবচেয়ে বড় অভিযোগ টাইপ ইরেজর। এটিতে, জেনেরিকগুলি রানটাইমের সময় প্রয়োগ করা হয় না। বিষয়টি নিয়ে কিছু সান ডক্সের লিঙ্ক এখানে দেওয়া হয়েছে ।
জেনেরিকগুলি মুছে ফেলা টাইপের মাধ্যমে প্রয়োগ করা হয়: জেনেরিক ধরণের তথ্য কেবল সংকলনের সময় উপস্থিত থাকে, তারপরে এটি সংকলক দ্বারা মুছে ফেলা হয়।
সি ++ টেমপ্লেটগুলি তাদের সি # এবং জাভা অংশগুলির তুলনায় প্রকৃতপক্ষে অনেক বেশি শক্তিশালী কারণ সেগুলি সংকলন সময় এবং সমর্থন বিশেষজ্ঞের জন্য মূল্যায়ন করা হয়। এটি টেমপ্লেট মেটা-প্রোগ্রামিংয়ের জন্য অনুমতি দেয় এবং সি ++ সংকলককে একটি টুরিং মেশিনের সমতুল্য করে তোলে (যেমন সংকলন প্রক্রিয়া চলাকালীন আপনি কোনও ট্যুরিং মেশিনের সাথে গণ্যযোগ্য যে কোনও কিছু গণনা করতে পারেন)।
দেখে মনে হচ্ছে, অন্যান্য খুব আকর্ষণীয় প্রস্তাবগুলির মধ্যে, জেনেরিকগুলি সংশোধন করার এবং পিছনের দিকে সামঞ্জস্যতা ভাঙার বিষয়ে একটি রয়েছে:
বর্তমানে, জেনেরিকগুলি ক্ষয় ব্যবহার করে প্রয়োগ করা হয়, যার অর্থ জেনেরিক ধরণের তথ্য রানটাইমে পাওয়া যায় না, যা কোনও ধরণের কোড লিখতে শক্ত করে তোলে। জেনেরিক্স পুরানো নন-জেনেরিক কোডের সাথে পিছনের সামঞ্জস্যকে সমর্থন করার জন্য এই পদ্ধতিতে কার্যকর করা হয়েছিল। সংশোধিত জেনেরিকগুলি জেনেরিক ধরণের তথ্য রানটাইমে উপলভ্য করে, যা উত্তরাধিকার নন-জেনেরিক কোডটি ভেঙে দেয়। যাইহোক, নীল গিটার পরে প্রকারের সামঞ্জস্যতা যাতে না ভাঙতে পারে তবে নির্দিষ্ট করে কেবল প্রকারগুলি পুনরায় সংশোধনযোগ্য করে তোলার প্রস্তাব দিয়েছে।
এনবি: আমার মতামত দেওয়ার মতো পর্যায়ে পয়েন্ট নেই, তাই উপযুক্ত উত্তরের মন্তব্য হিসাবে এটিকে নির্দ্বিধায় সরিয়ে দিন।
জনপ্রিয় বিশ্বাসগুলির বিপরীতে, যা আমি কখনই বুঝতে পারি না যে এটি থেকে এসেছে net নেট পশ্চাদপটে সামঞ্জস্যতা না ভাঙিয়ে সত্য জেনারিকগুলি প্রয়োগ করেছিল এবং তারা এর জন্য স্পষ্ট প্রচেষ্টা ব্যয় করেছিল। আপনাকে। জেনারিক। নেট 1.0 ব্যবহার করার জন্য আপনার জেনারিক। নেট 1.0 কোডটি জেনেরিকগুলিতে পরিবর্তন করতে হবে না। জেনেরিক এবং নন-জেনেরিক উভয় তালিকাগুলি এখনও নেট ফ্রেমওয়ার্ক 2.0 তে 4.0. অবধি পাওয়া যায়, ঠিক পিছনে সামঞ্জস্যতার কারণ ছাড়া অন্য কিছুই নয়। সুতরাং পুরানো কোডগুলি যা এখনও অ জেনেরিক অ্যারেলিস্ট ব্যবহার করেছে তা এখনও কাজ করবে এবং আগের মতো একই অ্যারেলিস্ট ক্লাস ব্যবহার করবে। পশ্চাদপদ কোডের সামঞ্জস্যতা সর্বদা ০.০ থেকে এখন পর্যন্ত বজায় রাখা হয় ... সুতরাং। নেট 4.0.০ তেও, আপনি যদি এখনও এটি বেছে নেন তবে আপনাকে ০.০ বিসিএল থেকে নন-জেনেরিক শ্রেণি ব্যবহার করার বিকল্প থাকতে হবে।
সুতরাং আমি ভাবি না যে জাভা সত্যিকারের জেনেরিকগুলিকে সমর্থন করার জন্য পিছিয়ে সামঞ্জস্যতা ভেঙে ফেলতে হবে।
ArrayList<Foo>
যা এটি একটি পুরানো পদ্ধতিতে যেতে চায় যা ArrayList
উদাহরণস্বরূপ একটি পপুলেশন করার কথা Foo
। যদি এটি একটি ArrayList<foo>
না ArrayList
হয় তবে কীভাবে এটি কাজ করে?