উত্তর:
তাদের মধ্যে একটি বড় পার্থক্য আছে। সি ++ এ আপনাকে জেনেরিক ধরণের জন্য কোনও শ্রেণি বা একটি ইন্টারফেস নির্দিষ্ট করতে হবে না। এজন্য আপনি আলগা টাইপিংয়ের ক্যাভ্যাট সহ সত্যই জেনেরিক ফাংশন এবং ক্লাস তৈরি করতে পারেন।
template <typename T> T sum(T a, T b) { return a + b; }
উপরের পদ্ধতিতে একই ধরণের দুটি অবজেক্ট যুক্ত করা হয় এবং যে কোনও ধরণের টিতে "+" অপারেটর উপলব্ধ থাকার জন্য এটি ব্যবহার করা যেতে পারে।
জাভাতে আপনাকে কোনও প্রকার নির্দিষ্ট করতে হবে যদি আপনি পাশ করা বস্তুগুলিতে পদ্ধতিগুলি কল করতে চান তবে এরকম কিছু:
<T extends Something> T sum(T a, T b) { return a.add ( b ); }
সি ++ জেনেরিক ফাংশন / ক্লাসগুলিতে কেবল শিরোনামগুলিতে সংজ্ঞায়িত করা যায়, যেহেতু সংকলকটি বিভিন্ন ধরণের (যা এটি দিয়ে থাকে) জন্য বিভিন্ন ফাংশন উত্পন্ন করে। সুতরাং সংকলন ধীর। জাভাতে এই সংকলনের একটি বড় পেনাল্টি নেই, তবে জাভা "ইরেজর" নামক একটি প্রযুক্তি ব্যবহার করে যেখানে জেনেরিক ধরণটি রানটাইমের সময় মুছে ফেলা হয়, তাই রানটাইমটিতে জাভা আসলে কল করছে ...
Something sum(Something a, Something b) { return a.add ( b ); }
জাভাতে জেনেরিক প্রোগ্রামিংটি আসলেই কার্যকর নয়, নতুন ফোরচ নির্মাণে সহায়তা করার জন্য এটি কেবল সামান্য সিনট্যাকটিক চিনি।
সম্পাদনা: উপযোগিতার বিষয়ে উপরোক্ত মতামতটি একজন তরুণ লিখেছেন self জাভা এর জেনেরিকস অবশ্যই প্রকারের সুরক্ষায় সহায়তা করে।
extends
অথবা হয় আকারে super
। উত্তরটি ভুল,
জাভা জেনারিকস ব্যাপকভাবে সি ++ টেমপ্লেট থেকে পৃথক।
মূলত সি ++ টেম্পলেটগুলিতে মূলত গৌরবযুক্ত প্রিপ্রোসেসর / ম্যাক্রো সেট ( দ্রষ্টব্য: যেহেতু কিছু লোক উপমা বোঝাতে অক্ষম বলে মনে হয়, তাই আমি বলছি না যে টেমপ্লেট প্রসেসিং একটি ম্যাক্রো)। জাভাতে তারা অবজেক্টগুলির বয়লারপ্লেট কাস্টিং হ্রাস করতে মূলত সিনট্যাকটিক চিনি। এখানে জাভা জেনেরিক বনাম সি ++ টেমপ্লেটগুলির একটি সুন্দর শালীন ভূমিকা রয়েছে ।
এই বিষয়টির বিশদটি জানাতে: আপনি যখন C ++ টেম্পলেট ব্যবহার করেন, আপনি মূলত কোডটির অন্য একটি অনুলিপি তৈরি করেন ঠিক যেমন আপনি #define
ম্যাক্রো ব্যবহার করেন । এটি আপনাকে int
টেমপ্লেট সংজ্ঞাতে প্যারামিটারগুলি রাখার মতো জিনিসগুলি করতে দেয় যা মঞ্জুরীর অ্যারে এবং এর মতো নির্ধারণ করে।
জাভা এর মতো কাজ করে না। জাভাতে java.lang.Object থেকে সমস্ত অবজেক্টস প্রজেক্ট , প্রাক জেনারিক্স, আপনি এই জাতীয় কোড লিখতে চাইবেন:
public class PhoneNumbers {
private Map phoneNumbers = new HashMap();
public String getPhoneNumber(String name) {
return (String)phoneNumbers.get(name);
}
...
}
কারণ সমস্ত জাভা সংগ্রহের ধরণগুলি অবজেক্টকে তাদের বেস ধরণের হিসাবে ব্যবহার করেছিল যাতে আপনি এগুলিতে কিছু রাখতে পারেন। জাভা 5 চারদিকে ঘুরছে এবং জেনেরিকগুলি যুক্ত করে যাতে আপনি এই জাতীয় জিনিসগুলি করতে পারেন:
public class PhoneNumbers {
private Map<String, String> phoneNumbers = new HashMap<String, String>();
public String getPhoneNumber(String name) {
return phoneNumbers.get(name);
}
...
}
এবং এগুলি সমস্ত জাভা জেনেরিক্স হ'ল: ingালাইয়ের অবজেক্টগুলির জন্য মোড়ক এর কারণ জাভা জেনারিক্স পরিমার্জনযোগ্য নয়। তারা টাইপ ইরেজোর ব্যবহার করে। এই সিদ্ধান্ত নেওয়া হয়েছিল কারণ জাভা জেনেরিক্স এতটা দেরিতে এসেছিল যে তারা পিছিয়ে থাকা সামঞ্জস্যতা ( Map<String, String>
যেহেতু যখনই Map
ডাকা হয় তখন ব্যবহারযোগ্য ) break এটি নেট / সি # এর সাথে তুলনা করুন যেখানে ধরণ মুছে ফেলা হয় না, যা সমস্ত ধরণের পার্থক্যের দিকে পরিচালিত করে (যেমন আপনি আদিম ধরণের এবং ব্যবহার করতে পারেন IEnumerable
এবংIEnumerable<T>
একে অপরের সাথে কোন সম্পর্ক বহন)।
এবং একটি জাভা 5+ সংকলক সহ সংকলিত জেনেরিকগুলি ব্যবহার করে একটি ক্লাস JDK 1.4- তে ধরে নেওয়া যায় (এটি অন্য কোনও বৈশিষ্ট্য বা ক্লাস ব্যবহার করে না যা জাভা 5+ প্রয়োজন)।
এজন্য জাভা জেনেরিকসকে সিনট্যাকটিক সুগার বলা হয় ।
তবে জেনেরিকস কীভাবে করবেন তার এই সিদ্ধান্তের এত গভীর প্রভাব রয়েছে যাতে (চমত্কার) জাভা জেনেরিক্স এফএকিউ সম্পর্কে লোকেদের অনেক প্রশ্নের উত্তর দেওয়ার জন্য উত্সাহিত করেছে।
সি ++ টেমপ্লেটগুলিতে জাভা জেনারিক্সের এমন অনেকগুলি বৈশিষ্ট্য রয়েছে যা:
আদিম ধরণের আর্গুমেন্ট ব্যবহার।
উদাহরণ স্বরূপ:
template<class T, int i>
class Matrix {
int T[i][i];
...
}
জাভা জেনেরিকসে আদিম ধরণের আর্গুমেন্ট ব্যবহারের অনুমতি দেয় না।
ডিফল্ট ধরণের আর্গুমেন্টগুলির ব্যবহার , যা জাভাতে আমি মিস করি এমন একটি বৈশিষ্ট্য তবে এর পিছনে সামঞ্জস্যের কারণগুলি রয়েছে;
উদাহরণ স্বরূপ:
public class ObservableList<T extends List> {
...
}
এটি সত্যই জোর দেওয়া দরকার যে বিভিন্ন যুক্তিযুক্ত টেম্পলেট অনুরোধগুলি সত্যই বিভিন্ন ধরণের। তারা স্থির সদস্যদেরও ভাগ করে না। জাভা এ ক্ষেত্রে হয় না।
পরিপূর্ণতার জন্য জেনেরিকের সাথে পার্থক্যগুলি বাদ দিয়ে, এখানে সি ++ এবং জাভা (এবং অন্য একটি ) এর একটি প্রাথমিক তুলনা দেওয়া হয়েছে ।
এবং আমি জাভা মধ্যে চিন্তাভাবনা বলতে পারেন । সি ++ প্রোগ্রামার হিসাবে অবজেক্টের মতো প্রচুর ধারণাটি ইতিমধ্যে দ্বিতীয় প্রকৃতি হতে পারে তবে সূক্ষ্ম পার্থক্য রয়েছে তাই আপনি অংশগুলি স্কিম করেও একটি প্রাথমিক পাঠ্য রাখা সার্থক হতে পারে।
জাভা শেখার সময় আপনি যা শিখবেন তার অনেকগুলি হ'ল সমস্ত গ্রন্থাগার (উভয় স্ট্যান্ডার্ড - জেডিকে কী আসে - এবং নন স্ট্যান্ডার্ড, যার মধ্যে স্প্রিংয়ের মতো সাধারণত ব্যবহৃত জিনিস অন্তর্ভুক্ত থাকে)। জাভা সিনট্যাক্স সি ++ সিনট্যাক্সের চেয়ে আরও ভার্বোজ এবং এতে প্রচুর সি ++ বৈশিষ্ট্য নেই (যেমন অপারেটর ওভারলোডিং, একাধিক উত্তরাধিকার, ধ্বংসকারী প্রক্রিয়া ইত্যাদি) তবে এটি কঠোরভাবে সি ++ এর উপসেট হিসাবে তৈরি করে না।
Map map = new HashMap<String, String>
। এর অর্থ আপনি কোনও পুরানো জেভিএম এ নতুন কোড স্থাপন করতে পারেন এবং এটি বাইকোডের মিলের কারণে চলবে।
সি ++ এর টেমপ্লেট রয়েছে। জাভাতে জেনেরিকস রয়েছে, যা দেখতে সি ++ টেম্পলেটগুলির মতো ধরণের ধরণের সাজানো, তবে সেগুলি খুব আলাদা।
নাম দ্বারা বোঝা যায়, টেমপ্লেটগুলি (এটির জন্য অপেক্ষা করুন ...) টেমপ্লেট সংকলক সরবরাহ করে যা এটি টেমপ্লেটগুলির পরামিতিগুলি পূরণ করে টাইপ-নিরাপদ কোড তৈরি করতে ব্যবহার করতে পারে।
জেনেরিকস, যেমন আমি তাদের বুঝতে পারি, অন্যদিকে কাজ করুন: সংকলক দ্বারা টাইপ পরামিতিগুলি ব্যবহার করা কোডগুলি টাইপ-সেফ কিনা তা যাচাই করতে ব্যবহৃত হয়, তবে ফলাফল কোডটি বিনা প্রকারেই তৈরি করা হয়।
সি ++ টেমপ্লেটগুলি সত্যই একটি ভাল ম্যাক্রো সিস্টেম হিসাবে এবং জাভা জেনেরিকগুলি স্বয়ংক্রিয়ভাবে টাইপকাস্টগুলি উত্পাদন করার সরঞ্জাম হিসাবে ভাবেন as
const
। সি -+ এ থাকা কোনও বস্তুকে const
পয়েন্টারের মাধ্যমে সংশোধন করা যাবে না যতক্ষণ না const
-তা দূরে দেওয়া হয়। তেমনি, জাভাতে জেনেরিক প্রকারের দ্বারা তৈরি প্রকট ক্যাসেটগুলি "নিরাপদ" হওয়ার গ্যারান্টিযুক্ত যদি না ধরণের পরামিতিগুলি ম্যানুয়ালি কোডের কোথাও দূরে কাস্ট করা থাকে।
C ++ টেমপ্লেটগুলিতে রয়েছে এমন আরও একটি বৈশিষ্ট্য যা জাভা জেনেরিকগুলি বিশেষায়িত নয়। এটি আপনাকে নির্দিষ্ট ধরণের জন্য আলাদা বাস্তবায়ন করতে দেয়। উদাহরণস্বরূপ, বাকী প্রকারের জন্য জেনেরিক সংস্করণ থাকা সত্ত্বেও আপনি উদাহরণস্বরূপ, কোনও int এর জন্য একটি অত্যন্ত অনুকূলিত সংস্করণ রাখতে পারেন। অথবা আপনার পয়েন্টার এবং নন-পয়েন্টার ধরণের বিভিন্ন সংস্করণ থাকতে পারে। আপনি যদি কোনও পয়েন্টার হস্তান্তরিত করেন তবে আপনি যদি অবনতিযুক্ত বস্তুটিতে কাজ করতে চান তবে এটি কার্যকর হবে।
ফিলিপ ওয়েডলারের জাভা জেনেরিকস এবং সংগ্রহগুলিতে মরিস নাফটালিনের এই বিষয়ের একটি দুর্দান্ত ব্যাখ্যা রয়েছে । আমি এই বই এর জন্য জোর পরামর্শ দিচ্ছি। উদ্ধৃতি থেকে:
জাভাতে জেনেরিকস সি ++ তে টেম্পলেটগুলির অনুরূপ। ... বাক্য গঠন ইচ্ছাকৃতভাবে একই এবং শব্দার্থবিজ্ঞান ইচ্ছাকৃতভাবে পৃথক। ... শব্দার্থকভাবে, জাভা জেনেরিকগুলি মুছে ফেলা দ্বারা সংজ্ঞায়িত করা হয়, যেখানে সি ++ টেম্পলেটগুলি সম্প্রসারণ দ্বারা সংজ্ঞায়িত করা হয়।
এখানে সম্পূর্ণ ব্যাখ্যা পড়ুন ।
(সূত্র: ওরিলি.কম )
মূলত, এএফএআইকি, সি ++ টেমপ্লেটগুলি প্রতিটি ধরণের জন্য কোডের একটি অনুলিপি তৈরি করে, যখন জাভা জেনেরিকগুলি একই কোড ব্যবহার করে।
হ্যাঁ, আপনি বলতে পারেন যে সি ++ টেম্পলেটটি জাভা জেনেরিক ধারণার সমতুল্য (যদিও আরও সঠিকভাবে বলতে গেলে জাভা জেনেরিকগুলি ধারণার ক্ষেত্রে সি ++ এর সমতুল্য)
আপনি যদি সি ++ এর টেম্পলেট প্রক্রিয়াটির সাথে পরিচিত হন তবে আপনি ভাবেন যে জেনেরিকগুলি সমান, তবে মিলটি অতিমাত্রায়। জেনারিক্স প্রতিটি বিশেষায়নের জন্য একটি নতুন ক্লাস তৈরি করে না, বা তারা "টেম্পলেট মেটাপোগ্র্যামিং" এর অনুমতি দেয় না।
থেকে: জাভা জেনারিক্স
সি ++ টেমপ্লেটগুলির আরেকটি সুবিধা হ'ল বিশেষায়িতকরণ।
template <typename T> T sum(T a, T b) { return a + b; }
template <typename T> T sum(T* a, T* b) { return (*a) + (*b); }
Special sum(const Special& a, const Special& b) { return a.plus(b); }
এখন, আপনি যদি পয়েন্টারের সাথে সমষ্টি কল করেন তবে দ্বিতীয় পদ্ধতিটি কল করা হবে, আপনি যদি পয়েন্টারবিহীন অবজেক্টের সাথে সমষ্টি কল করেন তবে প্রথম পদ্ধতিটি কল করা হবে এবং আপনি যদি বস্তুগুলির sum
সাথে কল করেন Special
তবে তৃতীয়টিকে ডাকা হবে। জাভা দিয়ে এটা সম্ভব বলে আমি মনে করি না।
আমি এটি একটি বাক্যে সমষ্টি করব: টেমপ্লেটগুলি নতুন ধরণের তৈরি করে, জেনেরিকগুলি বিদ্যমান প্রকারগুলিকে সীমাবদ্ধ করে।
@Keith:
এই কোডটি আসলে ভুল এবং ছোট গ্লিটস বাদে ( template
বাদ দেওয়া, বিশেষায়নের বাক্য গঠন আলাদাভাবে দেখায়), আংশিক বিশেষায়নের কাজটি কেবলমাত্র শ্রেণীর টেম্পলেটগুলিতে ফাংশন টেম্পলেটগুলিতে কাজ করে না । কোডটি যদিও আংশিক টেম্পলেট বিশেষকরণ ছাড়াই কাজ করবে, পরিবর্তে প্লেইন পুরাতন ওভারলোডিং ব্যবহার করে:
template <typename T> T sum(T a, T b) { return a + b; }
template <typename T> T sum(T* a, T* b) { return (*a) + (*b); }
নীচের উত্তরটি ক্র্যাকিং দ্য কোডিং ইন্টারভিউ সলিউশন বইটি থেকে অধ্যায় 13-এ দেওয়া হয়েছে, যা আমার মনে হয় খুব ভাল।
জাভা জেনেরিকের প্রয়োগটি "টাইপ ইরেজোর:" এর উত্স কোডটি জাভা ভার্চুয়াল মেশিন (জেভিএম) বাইটকোডে অনুবাদ করা হলে প্যারামিটারাইজড প্রকারগুলি সরিয়ে দেয় example উদাহরণস্বরূপ, ধরুন আপনার জাভা কোডটি নীচে রয়েছে:
Vector<String> vector = new Vector<String>();
vector.add(new String("hello"));
String str = vector.get(0);
সংকলনের সময়, এই কোডটিতে আবার লিখিত হয়:
Vector vector = new Vector();
vector.add(new String("hello"));
String str = (String) vector.get(0);
জাভা জেনেরিকের ব্যবহার আমাদের দক্ষতা সম্পর্কে সত্যই খুব বেশি পরিবর্তন ঘটেনি; এটি কেবল জিনিসগুলিকে কিছুটা সুন্দর করে তুলেছে। এই কারণে, জাভা জেনেরিকগুলিকে মাঝে মাঝে "সিনট্যাকটিক চিনি: 'বলা হয়।
এটি সি ++ থেকে বেশ আলাদা। সি ++ তে টেমপ্লেটগুলি মূলত গৌরবযুক্ত ম্যাক্রো সেট হয়, সংকলক প্রতিটি প্রকারের জন্য টেম্পলেট কোডের একটি নতুন অনুলিপি তৈরি করে। এর প্রমাণ এই যে মাইক্লাসের একটি উদাহরণ মাই ক্লাসের সাথে একটি স্ট্যাটিক ভেরিয়েবল ভাগ করে নেবে না। মাইক্লাসের দু'টি উদাহরণগুলি তবে একটি স্থিতিশীল ভেরিয়েবল ভাগ করবে।
/*** MyClass.h ***/
template<class T> class MyClass {
public:
static int val;
MyClass(int v) { val v;}
};
/*** MyClass.cpp ***/
template<typename T>
int MyClass<T>::bar;
template class MyClass<Foo>;
template class MyClass<Bar>;
/*** main.cpp ***/
MyClass<Foo> * fool
MyClass<Foo> * foo2
MyClass<Bar> * barl
MyClass<Bar> * bar2
new MyClass<Foo>(10);
new MyClass<Foo>(15);
new MyClass<Bar>(20);
new MyClass<Bar>(35);
int fl fool->val; // will equal 15
int f2 foo2->val; // will equal 15
int bl barl->val; // will equal 35
int b2 bar2->val; // will equal 35
জাভাতে, স্ট্যাটিক ভেরিয়েবলগুলি মাই ক্লাসের দৃষ্টান্তগুলিতে ভাগ করা হয়, diffrerent ধরণের পরামিতি নির্বিশেষে।
জাভা জেনেরিকস এবং সি ++ টেম্পলেটগুলির মধ্যে অন্যান্য কয়েকটি পার্থক্য রয়েছে। এর মধ্যে রয়েছে:
টেমপ্লেটগুলি ম্যাক্রো সিস্টেম ব্যতীত আর কিছুই নয়। সিনট্যাক্স চিনি। প্রকৃত সংকলনের আগে এগুলি সম্পূর্ণরূপে প্রসারিত হয় (বা কমপক্ষে সংকলকরা যেমন আচরণ করে তেমন আচরণ করে)।
উদাহরণ:
ধরা যাক আমরা দুটি ফাংশন চাই। একটি ফাংশন দুটি সংখ্যার (তালিকা, অ্যারে, ভেক্টর, যাই হোক না কেন) সংখ্যায় নেয় এবং তাদের অভ্যন্তরীণ পণ্যটি দেয়। অন্য একটি ফাংশন একটি দৈর্ঘ্য নেয়, সেই দৈর্ঘ্যের দুটি ক্রম উত্পন্ন করে, তাদের প্রথম কার্যক্রমে পাস করে এবং ফলাফলটি প্রদান করে। ধরাটি হ'ল আমরা দ্বিতীয় ফাংশনে ভুল করতে পারি, যাতে এই দুটি ফাংশনটি একই দৈর্ঘ্যের না হয়। এক্ষেত্রে আমাদের সতর্ক করতে আমাদের সংকলক প্রয়োজন। যখন প্রোগ্রামটি চলছে তখন নয়, যখন এটি সংকলন করছে।
জাভাতে আপনি এরকম কিছু করতে পারেন:
import java.io.*;
interface ScalarProduct<A> {
public Integer scalarProduct(A second);
}
class Nil implements ScalarProduct<Nil>{
Nil(){}
public Integer scalarProduct(Nil second) {
return 0;
}
}
class Cons<A implements ScalarProduct<A>> implements ScalarProduct<Cons<A>>{
public Integer value;
public A tail;
Cons(Integer _value, A _tail) {
value = _value;
tail = _tail;
}
public Integer scalarProduct(Cons<A> second){
return value * second.value + tail.scalarProduct(second.tail);
}
}
class _Test{
public static Integer main(Integer n){
return _main(n, 0, new Nil(), new Nil());
}
public static <A implements ScalarProduct<A>>
Integer _main(Integer n, Integer i, A first, A second){
if (n == 0) {
return first.scalarProduct(second);
} else {
return _main(n-1, i+1,
new Cons<A>(2*i+1,first), new Cons<A>(i*i, second));
//the following line won't compile, it produces an error:
//return _main(n-1, i+1, first, new Cons<A>(i*i, second));
}
}
}
public class Test{
public static void main(String [] args){
System.out.print("Enter a number: ");
try {
BufferedReader is =
new BufferedReader(new InputStreamReader(System.in));
String line = is.readLine();
Integer val = Integer.parseInt(line);
System.out.println(_Test.main(val));
} catch (NumberFormatException ex) {
System.err.println("Not a valid number");
} catch (IOException e) {
System.err.println("Unexpected IO ERROR");
}
}
}
সি # তে আপনি প্রায় একই জিনিস লিখতে পারেন। এটি C ++ এ পুনরায় লেখার চেষ্টা করুন এবং এটি সংকলন করবে না, টেমপ্লেটের অসীম প্রসারণ সম্পর্কে অভিযোগ করবে।
আমি উদ্ধৃত করতে চাই askanydifference এখানে:
সি ++ এবং জাভার মধ্যে প্রধান পার্থক্য প্ল্যাটফর্মের উপর তাদের নির্ভরতার মধ্যে রয়েছে। যদিও, সি ++ প্ল্যাটফর্ম নির্ভর ভাষা, জাভা প্ল্যাটফর্ম স্বতন্ত্র ভাষা।
উপরের বিবৃতিটি কেন সি ++ সত্য জেনেরিক প্রকার সরবরাহ করতে সক্ষম তা কারণ। যদিও জাভাতে কঠোর চেকিং রয়েছে এবং তাই তারা সি ++ এর মতো জেনেরিকগুলি ব্যবহার করার অনুমতি দেয় না।