সি # এবং জাভাতে জেনেরিক্স এবং সি ++ তে টেমপ্লেটগুলির মধ্যে পার্থক্যগুলি কী? [বন্ধ]


203

আমি বেশিরভাগ জাভা ব্যবহার করি এবং জেনেরিকগুলি তুলনামূলকভাবে নতুন। আমি পড়তে থাকি যে জাভা ভুল সিদ্ধান্ত নিয়েছে বা that .NET এর আরও ভাল বাস্তবায়ন ইত্যাদি রয়েছে etc.

তো, জেনেরিকসে সি ++, সি #, জাভার মধ্যে প্রধান পার্থক্যগুলি কী? প্রত্যেকের পেশাদার / কনস?

উত্তর:


364

আমি আওয়াজে আমার কন্ঠ যুক্ত করব এবং বিষয়গুলি পরিষ্কার করার জন্য এক ছুরিকাঘাত করব:

সি # জেনারিকস আপনাকে এই জাতীয় কিছু ঘোষণা করার অনুমতি দেয়।

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 () ফাংশন থাকে, তবে এটি সংকলন করবে। যদি তারা না করে তবে তা হবে না। সহজ।

তাই সেখানে যদি আপনি এটি আছে :-)


8
সি # তে রেফারেন্স প্রকারের জন্য উত্পন্ন সিউডোক্লেসগুলি একই বাস্তবায়নটি ভাগ করে দেয় যাতে আপনি ঠিক তালিকার তালিকাভুক্ত হন না। পরীক্ষা করে দেখুন blogs.msdn.com/ericlippert/archive/2009/07/30/...
পাযত্র Czapla

4
না, আপনি জেনারিকস ব্যবহার করে জাভা 5 কোডটি সংকলন করতে পারবেন না এবং এটি পুরানো 1.4 ভিএম-তে চালিত হবেন (কমপক্ষে সান জেডিকে এটি বাস্তবায়ন করে না Some কিছু তৃতীয় পক্ষের সরঞ্জামগুলি করেন)) আপনি যা করতে পারেন তা হ'ল পূর্ববর্তী সংকলিত 1.4 জেআর ব্যবহার করুন 1.5 / 1.6 কোড।
ফিনিউ

4
int addNames<T>( T first, T second ) { return first + second; }আপনি C # তে লিখতে পারবেন না এমন বিবৃতিতে আমি আপত্তি জানাই । জেনেরিক টাইপটি একটি ইন্টারফেসের পরিবর্তে কোনও শ্রেণিতে সীমাবদ্ধ হতে পারে এবং এতে +অপারেটরের সাথে কোনও শ্রেণি ঘোষণার উপায় রয়েছে ।
মাশমাগার

4
@ আলেকজান্দার মালখোভ এটি উদ্দেশ্যমূলক নয়। মূল বক্তব্যটি সি ++ এর আইডিয়োম সম্পর্কে শিক্ষিত করা ছিল না, তবে একই ভাষার কোডের টুকরোটি প্রতিটি ভাষা কীভাবে আলাদাভাবে পরিচালনা করা হয় তা চিত্রিত করার জন্য। এই লক্ষ্যটি কোডের চেয়ে আরও ভিন্ন ভিন্নরূপে অর্জন করা আরও কঠিন ছিল
অরিয়ন এডওয়ার্ডস

3
@ ফ্রেসনেল আমি নীতিগতভাবে একমত, তবে আমি যদি সেই স্নিপেটটি আইডিয়োমেটিক সি ++ তে লিখে থাকি তবে এটি সি # / জাভা বিকাশকারীদের পক্ষে অনেক কম বোধগম্য হত এবং তাই (আমি বিশ্বাস করি) পার্থক্য ব্যাখ্যা করার জন্য আরও খারাপ কাজ করতে পারতাম। আসুন এর এক :
অরিওন এডওয়ার্ডস

61

সি ++ খুব কমই "জেনেরিক্স" পরিভাষা ব্যবহার করে। পরিবর্তে, "টেমপ্লেট" শব্দটি ব্যবহৃত হয়েছে এবং আরও সঠিক। টেমপ্লেটগুলি জেনেরিক নকশা অর্জনের জন্য একটি কৌশল বর্ণনা করে ।

সি ++ টেমপ্লেট দুটি মূল কারণে সি # এবং জাভা উভয়ই প্রয়োগ করে তার থেকে খুব আলাদা। প্রথম কারণটি হ'ল সি ++ টেমপ্লেটগুলি কেবল সংকলন-টাইম ধরণের আর্গুমেন্টকে অনুমতি দেয় না তবে সংকলন-কাল কনস্ট-মান যুক্তিগুলিও দেয়: টেমপ্লেটগুলি পূর্ণসংখ্যা বা এমনকি ফাংশন স্বাক্ষর হিসাবেও দেওয়া যেতে পারে। এর অর্থ হ'ল সংকলনের সময় আপনি বেশ কিছু মজার স্টাফ করতে পারেন, যেমন গণনা:

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*.

আমি মাঝে মাঝে। নেট এর জেনেরিক বৈশিষ্ট্যটি কামনা করি যাতে নেট ছাড়াও জিনিসগুলি কী হিসাবে ব্যবহার করার অনুমতি দেওয়া যেতে পারে। যদি মান-ধরণের অ্যারেগুলি ফ্রেমওয়ার্কের একটি অংশ হত (আমি অবাক হয়েছি তারা একরকম নয়, কাঠামোর মধ্যে স্থির আকারের অ্যারেগুলি এম্বেড করে এমন পুরানো এপিআইগুলির সাথে ইন্টারঅ্যাক্ট করার প্রয়োজনীয়তা দেখায়), এটি ঘোষণার জন্য কার্যকর হবে শ্রেণিতে কয়েকটি স্বতন্ত্র আইটেম এবং তারপরে একটি মান-টাইপ অ্যারে যার আকার জেনেরিক প্যারামিটার ছিল। এটি হ'ল নিকটতম যেটি আসতে পারে তা হ'ল একটি শ্রেণি অবজেক্ট যা পৃথক আইটেম ধারণ করে এবং তারপরে অ্যারে ধারণ করে পৃথক কোনও বস্তুর রেফারেন্সও ধারণ করে।
সুপারক্যাট

@ সুপের্যাট আপনি যদি লিগ্যাসি এপিআইয়ের সাথে ইন্টারঅ্যাক্ট করেন তবে ধারণাটি হল মার্শেলিং ব্যবহার করা (যা গুণাবলীর মাধ্যমে বর্ণিত হতে পারে)। সিএলআর-তে যাইহোক স্থির আকারের অ্যারে নেই তাই নন-টাইপ টেম্পলেট যুক্তিযুক্ত হওয়া এখানে কোনও উপকারে আসবে না।
কনরাড রুডল্ফ

আমি অনুমান করি যে আমি কী অবাক হই তা হ'ল মনে হচ্ছে স্থির আকারের মান ধরণের অ্যারেগুলি শক্ত হওয়া উচিত ছিল না এবং এটি অনেকগুলি ডেটা প্রকারকে মানের পরিবর্তে রেফারেন্স দ্বারা মার্শাল করার অনুমতি দিত। যদিও মার্শাল বাই-মানটি সেই ক্ষেত্রে কার্যকর হতে পারে যা প্রকৃতপক্ষে অন্য কোনওভাবে পরিচালনা করা যায় না, আমি মার্শাল-বাই-রেফকে ব্যবহারযোগ্য প্রায় সব ক্ষেত্রেই শ্রেষ্ঠ বলে বিবেচনা করব, সুতরাং এই জাতীয় ক্ষেত্রে স্থির করে স্ট্রাক্ট অন্তর্ভুক্ত করার অনুমতি দেয় আকারযুক্ত অ্যারেগুলি একটি দরকারী বৈশিষ্ট্য বলে মনে হত।
সুপারক্যাট

বিটিডব্লিউ, অন্য পরিস্থিতি যেখানে অ-টাইপ জেনেরিক প্যারামিটারগুলি কার্যকর হবে তা হ'ল ডাটা টাইপের সাথে যা মাত্রিক পরিমাণকে উপস্থাপন করে। একটি পরিমাণের প্রতিনিধিত্বকারী উদাহরণগুলির মধ্যে মাত্রিক তথ্য অন্তর্ভুক্ত করতে পারে, তবে কোনও ধরণের মধ্যে এই জাতীয় তথ্য থাকার ফলে এটি নির্দিষ্ট করতে পারে যে কোনও সংকলন নির্দিষ্ট মাত্রিক ইউনিটের প্রতিনিধিত্বকারী অবজেক্টগুলিকে ধারণ করবে।
সুপারক্যাট

35

অ্যান্ডারস হেজলসবার্গ নিজেই এখানে পার্থক্য বর্ণনা করেছেন "জেনারিকস ইন সি #, জাভা এবং সি ++ "।


আমি সত্যিই সেই সাক্ষাত্কার পছন্দ করি। এটি সি-জেনারিকগুলি নিয়ে কী চলছে তা আমার মতো নন-সি # ছেলের পক্ষে এটি স্পষ্ট করে তোলে।
জোহানেস স্কাউব -

18

ইতিমধ্যেই ভাল উত্তর অনেক আছে কি পার্থক্য আছে, তাই আমাকে একটি কিছুটা ভিন্ন আঙ্গিক দিতে দিন যোগ কেন

যেমনটি আগেই ব্যাখ্যা করা হয়েছিল, মূল পার্থক্যটি টাইপ ইরেজর , অর্থাৎ জাভা সংকলক জেনেরিক প্রকারগুলি মুছে দেয় এবং এগুলি উত্পন্ন বাইকোডে শেষ হয় না। তবে, প্রশ্নটি হল: কেউ কেন এমন করবে? এটা বোঝা যায় না! নাকি তা করে?

ঠিক আছে, বিকল্প কি? আপনি ভাষায় জেনেরিক্স বাস্তবায়ন না থাকে, তাহলে যেখানে না আপনি তাদের বাস্তবায়ন? এবং উত্তরটি হ'ল ভার্চুয়াল মেশিনে। যা পিছনের দিকে সামঞ্জস্যতা ভঙ্গ করে।

অন্যদিকে মুছে ফেলা টাইপ আপনাকে জেনেরিক ক্লায়েন্টগুলিকে নন-জেনেরিক লাইব্রেরির সাথে মিশ্রিত করতে দেয়। অন্য কথায়: জাভা 5 তে সংকলিত কোডটি এখনও জাভা 1.4 এ স্থাপন করা যেতে পারে।

মাইক্রোসফ্ট অবশ্য জেনেরিকের জন্য সামনের সামঞ্জস্যতা ভেঙে ফেলার সিদ্ধান্ত নিয়েছে। এজন্য। নেট জেনেরিক্স জাভা জেনেরিক্সের চেয়ে "ভাল"।

অবশ্যই, সান বোকা বা কাপুরুষ নয়। তারা "ছত্রভঙ্গ" হওয়ার কারণটি ছিল যে জেনারিকগুলি প্রবর্তন করার সময় জাভাটি নেট থেকে অনেক বেশি বয়স্ক এবং বেশি বিস্তৃত ছিল। (এগুলি উভয় জগতে মোটামুটি একই সময়ে প্রবর্তিত হয়েছিল।) পিছনের দিকে সামঞ্জস্যতা ভঙ্গ করা একটি বিশাল ব্যথা হত।

আরও একটি উপায় রাখুন: জাভাতে জেনেরিক্স ভাষার একটি অংশ (যার অর্থ তারা কেবল জাভাতে প্রয়োগ হয়, অন্য ভাষায় নয়), নেট এ তারা ভার্চুয়াল মেশিনের অংশ (যার অর্থ তারা সমস্ত ভাষায় প্রয়োগ করে , না কেবল সি # এবং ভিজ্যুয়াল বেসিক N নেট)।

লিনকিউ, ল্যাম্বডা এক্সপ্রেশন, স্থানীয় ভেরিয়েবল টাইপ অনুমান, বেনামি প্রকার এবং অভিব্যক্তি গাছের মতো .NET বৈশিষ্ট্যগুলির সাথে এটির তুলনা করুন: এগুলি সমস্ত ভাষার বৈশিষ্ট্য। এই কারণেই ভিবি.এনইটি এবং সি # এর মধ্যে সূক্ষ্ম পার্থক্য রয়েছে: যদি এই বৈশিষ্ট্যগুলি ভিএম এর অংশ হয়, তবে সমস্ত ভাষায় সেগুলি একই হবে । তবে সিএলআর পরিবর্তিত হয়নি: নেট .২.০ তে যেমন ছিল নেট SP.৩ এসপি 1 তে এটি এখনও একই। আপনি একটি সি # প্রোগ্রাম সংকলন করতে পারেন যা .NET 3.5 সংকলক সহ লিনকিউ ব্যবহার করে এবং এটি নেট .০.০.০ এ চালিত করুন, আপনি যদি কোনও নেট নেট ৩.৫ লাইব্রেরি ব্যবহার না করেন। এটি জেনেরিকস এবং .NET 1.1 এর সাথে কাজ করবে না , তবে এটি জাভা এবং জাভা 1.4 এর সাথে কাজ করবে


3
লিনকুই মূলত একটি লাইব্রেরি বৈশিষ্ট্য (যদিও সি # এবং ভিবি এর পাশাপাশি সিনট্যাক্স চিনি যুক্ত করেছে)। ২.০ সিএলআর লক্ষ্য করে এমন যে কোনও ভাষা লাইনকিউর সম্পূর্ণ ব্যবহার করতে পারে কেবলমাত্র সিস্টেম.কোর অ্যাসেম্বলি লোড করে।
রিচার্ড বার্গ

হ্যাঁ, দুঃখিত, আমার আরও পরিষ্কার হওয়া উচিত ছিল। LINQ। আমি কোয়েরি সিনট্যাক্সের কথা উল্লেখ করছিলাম, মোনাডিক স্ট্যান্ডার্ড ক্যোয়ারী অপারেটরগুলি, লিনকিউ এক্সটেনশন পদ্ধতি বা আইকিউয়েরেবল ইন্টারফেস নয়। স্পষ্টতই, আপনি যে কোনও নেট ভাষা থেকে এগুলি ব্যবহার করতে পারেন।
জার্গ ডব্লু মিট্টাগ

1
আমি জাভা জন্য অন্য বিকল্প চিন্তা করছি। এমনকি ওরাকল পশ্চাদপটে সামঞ্জস্যতাও ভাঙতে চায় না, তারা টাইপ তথ্য মুছে ফেলা এড়াতে কিছু সংকলক কৌশল করতে পারে। উদাহরণস্বরূপ, ArrayList<T>একটি (লুকানো) স্ট্যাটিক Class<T>ক্ষেত্র সহ একটি নতুন অভ্যন্তরীণ নামযুক্ত প্রকার হিসাবে নির্গত হতে পারে । যতক্ষণ না জেনেরিক লিবের নতুন সংস্করণটি 1.5+ বাইট কোড সহ স্থাপন করা হয়েছে ততক্ষণ এটি 1.4- জেভিএমগুলিতে চালাতে সক্ষম হবে।
আর্থ ইঞ্জিন

14

আমার আগের পোস্টিং অনুসরণ করুন।

টেমপ্লেটগুলি আইডিই ব্যবহার না করেই, ইন্টেলিজেন্সে সি ++ এত অস্বাভাবিকভাবে ব্যর্থ হওয়ার একটি প্রধান কারণ। টেমপ্লেট বিশেষায়নের কারণে আইডিই কখনই নিশ্চিত হতে পারে না যে কোনও প্রদত্ত সদস্যের উপস্থিতি রয়েছে কি না। বিবেচনা:

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ালাই) সঞ্চালিত হবে যা প্রায়শই নির্মাণকারীর অনুরোধ। সংকলকটি আমাদের বলতে কী বলতে পারে তা বলতে পারে না তাই আমাদের এখানে বিভ্রান্ত করতে হবে।


2
আমি বেশ একমত। কিছু আশা আছে, যদিও। স্বতঃপূরণ সিস্টেম এবং সি ++ সংকলক অবশ্যই খুব কাছ থেকে ইন্টারঅ্যাক্ট করতে হবে। আমি নিশ্চিত যে ভিজ্যুয়াল স্টুডিওতে এই জাতীয় বৈশিষ্ট্যটি আর কখনও পাওয়া যাবে না, তবে জিনিসটি গ্রিপস / সিডিটি বা জিসিসির উপর ভিত্তি করে অন্য কোনও আইডিইতে ঘটতে পারে। আশা! :)
বেনোট

6

জাভা এবং সি # উভয়ই তাদের প্রথম ভাষা প্রকাশের পরে জেনেরিকগুলি চালু করেছিল। যাইহোক, জেনেরিকগুলি চালু করার সময় মূল পাঠাগারগুলি কীভাবে পরিবর্তিত হয়েছিল তার মধ্যে পার্থক্য রয়েছে। সি # এর জেনেরিকগুলি কেবল যাদু সংকলনকারী নয় এবং অতএব বিদ্যমান সামঞ্জস্যতা পিছনে সামঞ্জস্যতা না ভেঙে জেনারেট করা সম্ভব ছিল না ।

উদাহরণস্বরূপ, জাভাতে বিদ্যমান সংগ্রহ ফ্রেমওয়ার্ক সম্পূর্ণ জেনারাইজড হয়েছিল । জাভা সংগ্রহের ক্লাসগুলির জেনেরিক এবং উত্তরাধিকার নন-জেনেরিক সংস্করণ উভয়ই নেই। কিছু উপায়ে এটি অনেক বেশি পরিষ্কার - আপনার যদি সি # তে কোনও সংগ্রহের প্রয়োজন হয় তবে অ-জেনেরিক সংস্করণটি গ্রহণের খুব কম কারণ থাকতে পারে, তবে এই উত্তরাধিকারের শ্রেণিগুলি স্থানে রয়েছে, ল্যান্ডস্কেপটি বিশৃঙ্খলাবদ্ধ করে তোলে।

আর একটি উল্লেখযোগ্য পার্থক্য হ'ল জাভা এবং সি # তে এনাম ক্লাস। জাভার এনামের এই কিছুটা সংকটজনক সংজ্ঞা রয়েছে:

//  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
আর্থ ইঞ্জিন

4

11 মাস দেরীতে, তবে আমি মনে করি এই প্রশ্নটি কিছু জাভা ওয়াইল্ডকার্ড স্টাফের জন্য প্রস্তুত।

এটি জাভার একটি সিনট্যাক্টিকাল বৈশিষ্ট্য। ধরুন আপনার একটি পদ্ধতি রয়েছে:

public <T> void Foo(Collection<T> thing)

এবং ধরুন আপনার মেথড বডি তে টি টাইপ করার দরকার নেই। আপনি একটি নাম টি ঘোষণা করছেন এবং তারপরে কেবল একবার এটি ব্যবহার করছেন, তবে এর জন্য আপনার নাম কেন ভাবা উচিত? পরিবর্তে, আপনি লিখতে পারেন:

public void Foo(Collection<?> thing)

প্রশ্ন-চিহ্নটি সংকলকটিকে এই ভঙ্গিতে জিজ্ঞাসা করে যে আপনি একটি সাধারণ নামযুক্ত টাইপ পরামিতি ঘোষণা করেছেন যা কেবলমাত্র সেই জায়গায় একবার উপস্থিত হওয়া প্রয়োজন।

ওয়াইল্ডকার্ডগুলির সাথে আপনার করার মতো কিছুই নেই যা আপনি একটি নামের ধরণের পরামিতি (যা এই জিনিসগুলি সর্বদা সি ++ এবং সি # তে করা হয়) দিয়েও করতে পারবেন না।


2
আরও 11 মাস দেরী ... জাভা ওয়াইল্ডকার্ডগুলির সাথে আপনি এমন কিছু করতে পারেন যা আপনি নামধারী টাইপ পরামিতিগুলি দিয়ে করতে পারবেন না। আপনি এটি জাভাতে করতে পারেন: class Foo<T extends List<?>>এবং ব্যবহার করুন Foo<StringList>তবে সি # তে আপনাকে সেই অতিরিক্ত ধরণের পরামিতি যুক্ত করতে হবে: class Foo<T, T2> where T : IList<T2>এবং ক্লাঙ্কিটি ব্যবহার করতে হবে Foo<StringList, String>
আর মার্টিনহো ফার্নান্দেস

2

উইকিপিডিয়ায় জাভা / সি # জেনেরিকস এবং জাভা জেনেরিকস / সি ++ টেম্পলেটগুলির সাথে তুলনা করার জন্য দুর্দান্ত লেখাগুলি রয়েছেজেনেরিক্স মূল নিবন্ধ একটু বিশৃঙ্খল বলে মনে হয় কিন্তু তা কিছু ভাল তথ্য আছে।


1

সবচেয়ে বড় অভিযোগ টাইপ ইরেজর। এটিতে, জেনেরিকগুলি রানটাইমের সময় প্রয়োগ করা হয় না। বিষয়টি নিয়ে কিছু সান ডক্সের লিঙ্ক এখানে দেওয়া হয়েছে

জেনেরিকগুলি মুছে ফেলা টাইপের মাধ্যমে প্রয়োগ করা হয়: জেনেরিক ধরণের তথ্য কেবল সংকলনের সময় উপস্থিত থাকে, তারপরে এটি সংকলক দ্বারা মুছে ফেলা হয়।


1

সি ++ টেমপ্লেটগুলি তাদের সি # এবং জাভা অংশগুলির তুলনায় প্রকৃতপক্ষে অনেক বেশি শক্তিশালী কারণ সেগুলি সংকলন সময় এবং সমর্থন বিশেষজ্ঞের জন্য মূল্যায়ন করা হয়। এটি টেমপ্লেট মেটা-প্রোগ্রামিংয়ের জন্য অনুমতি দেয় এবং সি ++ সংকলককে একটি টুরিং মেশিনের সমতুল্য করে তোলে (যেমন সংকলন প্রক্রিয়া চলাকালীন আপনি কোনও ট্যুরিং মেশিনের সাথে গণ্যযোগ্য যে কোনও কিছু গণনা করতে পারেন)।


1

জাভাতে, জেনেরিকগুলি কেবল সংকলক স্তরের হয়, তাই আপনি পান:

a = new ArrayList<String>()
a.getClass() => ArrayList

নোট করুন যে 'এ' টাইপটি অ্যারে তালিকা, স্ট্রিংগুলির তালিকা নয়। সুতরাং কলা তালিকার ধরণটি () বানরের তালিকার সমান হবে।

তাই কথা বলতে.


1

দেখে মনে হচ্ছে, অন্যান্য খুব আকর্ষণীয় প্রস্তাবগুলির মধ্যে, জেনেরিকগুলি সংশোধন করার এবং পিছনের দিকে সামঞ্জস্যতা ভাঙার বিষয়ে একটি রয়েছে:

বর্তমানে, জেনেরিকগুলি ক্ষয় ব্যবহার করে প্রয়োগ করা হয়, যার অর্থ জেনেরিক ধরণের তথ্য রানটাইমে পাওয়া যায় না, যা কোনও ধরণের কোড লিখতে শক্ত করে তোলে। জেনেরিক্স পুরানো নন-জেনেরিক কোডের সাথে পিছনের সামঞ্জস্যকে সমর্থন করার জন্য এই পদ্ধতিতে কার্যকর করা হয়েছিল। সংশোধিত জেনেরিকগুলি জেনেরিক ধরণের তথ্য রানটাইমে উপলভ্য করে, যা উত্তরাধিকার নন-জেনেরিক কোডটি ভেঙে দেয়। যাইহোক, নীল গিটার পরে প্রকারের সামঞ্জস্যতা যাতে না ভাঙতে পারে তবে নির্দিষ্ট করে কেবল প্রকারগুলি পুনরায় সংশোধনযোগ্য করে তোলার প্রস্তাব দিয়েছে।

জাভা 7 প্রস্তাব সম্পর্কে অ্যালেক্স মিলারের নিবন্ধ


0

এনবি: আমার মতামত দেওয়ার মতো পর্যায়ে পয়েন্ট নেই, তাই উপযুক্ত উত্তরের মন্তব্য হিসাবে এটিকে নির্দ্বিধায় সরিয়ে দিন।

জনপ্রিয় বিশ্বাসগুলির বিপরীতে, যা আমি কখনই বুঝতে পারি না যে এটি থেকে এসেছে net নেট পশ্চাদপটে সামঞ্জস্যতা না ভাঙিয়ে সত্য জেনারিকগুলি প্রয়োগ করেছিল এবং তারা এর জন্য স্পষ্ট প্রচেষ্টা ব্যয় করেছিল। আপনাকে। জেনারিক। নেট 1.0 ব্যবহার করার জন্য আপনার জেনারিক। নেট 1.0 কোডটি জেনেরিকগুলিতে পরিবর্তন করতে হবে না। জেনেরিক এবং নন-জেনেরিক উভয় তালিকাগুলি এখনও নেট ফ্রেমওয়ার্ক 2.0 তে 4.0. অবধি পাওয়া যায়, ঠিক পিছনে সামঞ্জস্যতার কারণ ছাড়া অন্য কিছুই নয়। সুতরাং পুরানো কোডগুলি যা এখনও অ জেনেরিক অ্যারেলিস্ট ব্যবহার করেছে তা এখনও কাজ করবে এবং আগের মতো একই অ্যারেলিস্ট ক্লাস ব্যবহার করবে। পশ্চাদপদ কোডের সামঞ্জস্যতা সর্বদা ০.০ থেকে এখন পর্যন্ত বজায় রাখা হয় ... সুতরাং। নেট 4.0.০ তেও, আপনি যদি এখনও এটি বেছে নেন তবে আপনাকে ০.০ বিসিএল থেকে নন-জেনেরিক শ্রেণি ব্যবহার করার বিকল্প থাকতে হবে।

সুতরাং আমি ভাবি না যে জাভা সত্যিকারের জেনেরিকগুলিকে সমর্থন করার জন্য পিছিয়ে সামঞ্জস্যতা ভেঙে ফেলতে হবে।


লোকেরা যে ধরণের পশ্চাদপটে সামঞ্জস্যের কথা বলে তা নয়। রানটাইমটির জন্য পিছনের দিকের সামঞ্জস্যতা : .NET 2.0 এ জেনেরিকগুলি ব্যবহার করে লিখিত কোডটি .NET ফ্রেমওয়ার্ক / সিএলআর পুরানো সংস্করণে চালানো যায় না । একইভাবে, জাভা যদি "সত্য" জেনেরিক পরিচয় করিয়ে দেয় তবে নতুন জাভা কোডটি পুরানো জেভিএমগুলিতে চালাতে সক্ষম হবে না (কারণ এটিতে বাইটোকোডে ব্রেকিং পরিবর্তন প্রয়োজন)।
tzaman

এটা। নেট, জেনেরিক না। নির্দিষ্ট সিএলআর সংস্করণটি লক্ষ্যবস্তু করতে সর্বদা পুনরায় সংশ্লেষ প্রয়োজন। বাইটকোড সামঞ্জস্য আছে, কোডের সামঞ্জস্য আছে। এবং এছাড়াও, আমি নতুন জেনেরিকের তালিকাটি ব্যবহার করতে পুরানো তালিকা ব্যবহার করে এমন পুরানো কোডটি রূপান্তর করার প্রয়োজনীয়তার বিষয়ে বিশেষভাবে জবাব দিচ্ছিলাম, যা মোটেও সত্য নয়।
শিপি

1
আমি মনে করি লোকেরা সামনের সামঞ্জস্যের কথা বলছে । । .NET 2.0 কোডটি .NET 1.1 এ চালানোর জন্য, যা ভেঙ্গে যাবে কারণ 1.1 রানটাইম 2.0 "সিউডো-ক্লাস" সম্পর্কে কিছুই জানে না। তাহলে কি এমন হওয়া উচিত নয় যে "জাভা সত্য জেনেরিক বাস্তবায়ন করে না কারণ তারা সামনের সামঞ্জস্য বজায় রাখতে চায়"? (পিছনের চেয়ে বরং)
শিপি

সামঞ্জস্যতার বিষয়গুলি সূক্ষ্ম। আমি মনে করি না যে সমস্যাটি ছিল জাভাতে "আসল" জেনেরিকগুলি যুক্ত করা জাভাটির পুরানো সংস্করণগুলিতে ব্যবহার করা কোনও প্রোগ্রামকে প্রভাবিত করবে, বরং "নতুন উন্নত" জেনারিক ব্যবহার করা কোডটি পুরানো কোড সহ এই জাতীয় অবজেক্টগুলি বিনিময় করতে বেশ সময় ব্যয় করবে নতুন প্রকার সম্পর্কে কিছুই জানতেন না। ধরুন, উদাহরণস্বরূপ, কোনও প্রোগ্রামের এমন একটি রয়েছে ArrayList<Foo>যা এটি একটি পুরানো পদ্ধতিতে যেতে চায় যা ArrayListউদাহরণস্বরূপ একটি পপুলেশন করার কথা Foo। যদি এটি একটি ArrayList<foo>না ArrayListহয় তবে কীভাবে এটি কাজ করে?
সুপারক্যাট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.