পদ্ধতিতে অন্য পদ্ধতি মতো একই ক্ষয় রয়েছে ras


381

একই শ্রেণিতে নিম্নলিখিত দুটি পদ্ধতি থাকা কেন বৈধ নয়?

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

আমি পেয়েছি compilation error

মেথড অ্যাড (সেট) এর টেস্টের অন্য পদ্ধতি হিসাবে একই ইরেজর অ্যাড (সেট) থাকে।

আমি যখন এটির চারপাশে কাজ করতে পারি তখন আমি ভাবছিলাম যে জাভাক কেন এটি পছন্দ করে না।

আমি দেখতে পাচ্ছি যে অনেক ক্ষেত্রে, এই দুটি পদ্ধতির যুক্তিটি একই রকম হবে এবং এটি একটি একক দ্বারা প্রতিস্থাপিত হতে পারে

public void add(Set<?> set){}

পদ্ধতি, তবে এটি সবসময় হয় না।

এটি অতিরিক্ত বিরক্তিকর যদি আপনি দুটি পেতে চান constructorsযা সেই যুক্তিগুলি গ্রহণ করে কারণ আপনি কেবল একটিটির নাম পরিবর্তন করতে পারবেন না constructors


1
আপনার যদি ডেটা কাঠামো শেষ হয়ে যায় এবং আপনার আরও সংস্করণ প্রয়োজন?
ওমরি ইয়াদান

1
আপনি বেস সংস্করণগুলি থেকে উত্তরাধিকারসূত্রে কাস্টম ক্লাস তৈরি করতে পারেন।
উইল্লমা

1
ওপি, আপনি কি কনস্ট্রাক্টর সমস্যার কিছু সমাধান নিয়ে এসেছেন? আমাকে দুই ধরণের গ্রহণ করতে হবে Listএবং আমি কীভাবে এটি পরিচালনা করব তা জানি না।
টোম জ্যাটো - মনিকা

9
জাভা নিয়ে কাজ করার সময়, আমি সত্যিই সি # ... মিস করি
11

1
@ টোমাজাটো, আমি নির্ধারকটিতে ডমি প্যারাম যুক্ত করে সমাধান করেছি: বুলিয়ান নূপসাইনচার ওভারলোড।
Nthalk

উত্তর:


357

এই নিয়মটি লেগ্যাসি কোডে দ্বন্দ্ব এড়ানোর উদ্দেশ্যে তৈরি করা হয়েছে যা এখনও কাঁচা ধরণের ব্যবহার করে।

জেএলএস থেকে আঁকা কেন এটি অনুমোদিত নয়, এর একটি চিত্র এখানে মনে করুন, জেনারিকদের জাভা পরিচয় করানোর আগে আমি কিছু কোড লিখেছিলাম:

class CollectionConverter {
  List toList(Collection c) {...}
}

আপনি আমার ক্লাসটি এভাবে বাড়িয়ে দিন:

class Overrider extends CollectionConverter{
  List toList(Collection c) {...}
}

জেনেরিকের প্রবর্তনের পরে, আমি আমার লাইব্রেরি আপডেট করার সিদ্ধান্ত নিয়েছি।

class CollectionConverter {
  <T> List<T> toList(Collection<T> c) {...}
}

আপনি কোনও আপডেট করতে প্রস্তুত নন, তাই আপনি নিজের Overriderক্লাসটি একা রেখে যান। toList()পদ্ধতিটি সঠিকভাবে ওভাররাইড করার জন্য , ভাষা ডিজাইনাররা সিদ্ধান্ত নিয়েছিলেন যে কোনও কাঁচা টাইপ যে কোনও জেনারাইডেড টাইপের সাথে "ওভাররাইড-সমতুল্য"। এর অর্থ হ'ল যদিও আপনার পদ্ধতির স্বাক্ষরটি এখন আর আমার সুপারক্লাসের স্বাক্ষরের সাথে আনুষ্ঠানিকভাবে সমান নয়, তবুও আপনার পদ্ধতিটি ওভাররাইড করে।

এখন, সময় পার হয়ে যায় এবং আপনি সিদ্ধান্ত নেন যে আপনি নিজের ক্লাস আপডেট করতে প্রস্তুত। কিন্তু আপনি একটু আপ, এবং এর পরিবর্তে সম্পাদনা বিদ্যমান, কাঁচা এর স্ক্রু toList()পদ্ধতি, আপনি যোগ এই মত একটি নতুন পদ্ধতি:

class Overrider extends CollectionConverter {
  @Override
  List toList(Collection c) {...}
  @Override
  <T> List<T> toList(Collection<T> c) {...}
}

কাঁচা ধরণের ওভাররাইড সমতুল্যের কারণে, উভয় পদ্ধতিই toList(Collection<T>)পদ্ধতিটিকে ওভাররাইড করার জন্য একটি বৈধ আকারে । তবে অবশ্যই, সংকলকটির একটি একক পদ্ধতি সমাধান করা দরকার। এই অস্পষ্টতা দূর করতে, ক্লাসগুলিকে একাধিক পদ্ধতি থাকতে দেওয়া হয় না যা ওভাররাইড সমতুল্য are অর্থাৎ ক্ষয় করার পরে একই পরামিতি প্রকারের একাধিক পদ্ধতি।

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


3
দুর্দান্ত উত্তর এবং উদাহরণ! তবে আমি নিশ্চিত নই, তবে আমি যদি আপনার শেষ বাক্যটি সম্পূর্ণরূপে বুঝতে পারি ("কারণ পদ্ধতিটি রেজোলিউশন সংকলনকালে ঘটে যায়, ক্ষয় করার আগে, টাইপ রিফিকেশনটি এই কাজটি করার প্রয়োজন হয় না।")। আপনি কিছুটা ব্যাখ্যা করতে পারেন?
জোনাস আইসর

2
বোধ হয়। আমি কেবলমাত্র টেমপ্লেট পদ্ধতিতে টাইপ পুনঃনির্ধারণের কথা চিন্তা করে কিছুটা সময় ব্যয় করেছি, তবে হ্যাঁ: সংকলকটি নিশ্চিত করে তোলে যে টাইপ মোছার আগে সঠিক পদ্ধতিটি নির্বাচন করা হয়েছে। সুন্দর। যদি এটি লিগ্যাসি কোডের সামঞ্জস্যতার সমস্যাগুলির দ্বারা কলঙ্কিত না হয়।
জোনাস আইশার

1
@ ডেভালোল না, আমি এরকম কোনও বিকল্প সম্পর্কে অবগত নই javac
এরিকসন

13
আমি প্রথমবার জাভা ত্রুটির মুখোমুখি হইনি যা মোটেও ত্রুটি নয় এবং সংকলিত হতে পারে যদি কেবল জাভার লেখকরা সবাই যেমন সতর্কতা ব্যবহার করেন তেমনি। কেবল তারা মনে করেন যে তারা সবকিছু আরও ভাল জানেন।
টোমা জ্যাটো - মনিকা

1
@ টম্যাজাটো না, আমি এর জন্য কোনও পরিষ্কার কাজের কথা জানি না। আপনি যদি নোংরা কিছু চান, আপনি প্রকারটি নির্দেশ করতে সংজ্ঞায়িত করে এমন List<?>কিছু পাস enumকরতে পারেন। টাইপ-নির্দিষ্ট যুক্তি আসলে এনামের কোনও পদ্ধতিতে থাকতে পারে। বিকল্পভাবে, আপনি দুটি পৃথক কনস্ট্রাক্টর সহ এক শ্রেণির চেয়ে দুটি পৃথক ক্লাস তৈরি করতে চাইতে পারেন। প্রচলিত যুক্তি একটি সুপারক্লাস বা কোনও সহায়ক অবজেক্টে থাকত যেখানে উভয় প্রকারেরই প্রতিনিধি থাকে।
এরিকসন

117

জাভা জেনেরিকস টাইপ ইরেজর ব্যবহার করে। কোণ বন্ধনীগুলির বিটটি মুছে যায় ( <Integer>এবং <String>), সুতরাং আপনার দুটি সমাপ্তি স্বাক্ষরযুক্ত দুটি পদ্ধতিতে শেষ হবে ( add(Set)আপনি ত্রুটিতে দেখছেন)। এটি অনুমোদিত নয় কারণ রানটাইম প্রতিটি মামলার জন্য কোনটি ব্যবহার করবে তা জানত না।

জাভা যদি কখনও জেনারিক্সের সংশোধিত হয়ে যায়, তবে আপনি এটি করতে পারতেন, তবে সম্ভবত এটি এখনই খুব সম্ভবত।


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

5
@ স্টিলগার প্রতিবিম্বের মাধ্যমে কল করা বা পরিদর্শন করা পদ্ধতিটি থামানোর জন্য কী? Class.getMethods () দ্বারা ফিরিয়ে নেওয়া পদ্ধতির তালিকার দুটি অভিন্ন পদ্ধতি থাকবে, যার অর্থ হবে না।
অ্যাড্রিয়ান মৌআত

5
প্রতিবিম্ব তথ্যটিতে জেনেরিকের সাথে কাজ করার জন্য প্রয়োজনীয় মেটাডেটা থাকতে পারে / থাকতে পারে। যদি না হয় আপনি ইতিমধ্যে সংকলিত লাইব্রেরি আমদানি করেন তখন জাভা সংকলক জেনেরিক পদ্ধতি সম্পর্কে কীভাবে জানতে পারে?
Stilgar

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

1
এটি একটি সুনির্দিষ্ট উত্তর নয়, তবে এটি একটি কার্যকর কথাসাহিত্যে খুব দ্রুত সমস্যাটি সংক্ষিপ্ত করে তুলেছে: পদ্ধতির স্বাক্ষরগুলি খুব সমান, সংকলকটি পার্থক্যটি নাও বলতে পারে এবং তারপরে আপনি "অমীমাংসিত সংকলন সমস্যাগুলি" পেয়ে যাবেন।
worc

46

এর কারণ জাভা জেনারিকগুলি টাইপ ইরেজরের সাথে প্রয়োগ করা হয় ।

আপনার পদ্ধতিগুলি সংকলনের সময়ে এমন কিছুতে অনুবাদ করা হবে:

পদ্ধতির রেজোলিউশন সংকলন সময়ে ঘটে এবং প্রকারের পরামিতি বিবেচনা করে না। ( এরিকসনের উত্তর দেখুন )

void add(Set ii);
void add(Set ss);

উভয় পদ্ধতিতে টাইপ পরামিতি ছাড়াই একই স্বাক্ষর রয়েছে, অতএব ত্রুটি।


21

সমস্যা হল Set<Integer>এবং Set<String>আসলে একটি হিসাবে গণ্য করা হয় Setজেভিএম থেকে। সেটের জন্য কোনও প্রকার নির্বাচন করা (আপনার ক্ষেত্রে স্ট্রিং বা পূর্ণসংখ্যা) কেবল সংশ্লেষকারী দ্বারা ব্যবহৃত সিনট্যাকটিক চিনি। JVM Set<String>এবং এর মধ্যে পার্থক্য করতে পারে না Set<Integer>


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

@ এরিকসন এমনকি যখন সংকলকটি কী পদ্ধতিটি কল করতে জানে, এটি বাইটকোডের মতো হতে পারে না, তারা উভয়ই একইরকম দেখায়। কীভাবে কোনও মেথড কল নির্দিষ্ট করা যায় (Ljava/util/Collection;)Ljava/util/List;তা কার্যকর করা যায় না , এটি পরিবর্তন করতে হবে । আপনি ব্যবহার করতে পারেন (Ljava/util/Collection<String>;)Ljava/util/List<String>;, তবে এটি একটি বেমানান পরিবর্তন এবং আপনি যেখানে সমস্ত কিছু মুছে ফেলা হয় সেই জায়গায় আপনি অবিশ্বাস্য সমস্যার মধ্যে চলে যাবেন। আপনাকে সম্ভবত মুছে ফেলতে হবে পুরোপুরি, তবে এটি বেশ জটিল।
মার্টিনাস

@ মাআর্টিনাস হ্যাঁ, আমি সম্মত হলাম যে আপনাকে পদ্ধতি সুনির্দিষ্ট পরিবর্তন করতে হবে। আমি কিছু অবিশ্বাস্য সমস্যা যা তাদের সেই প্রচেষ্টাটি ত্যাগ করতে পরিচালিত করতে পেরেছিলাম তা চেষ্টা করার চেষ্টা করছি।
ইরিকসন

7

বিনা ধরণের একক পদ্ধতি নির্ধারণ করুন void add(Set ii){}

আপনার পছন্দ অনুসারে পদ্ধতিটি কল করার সময় আপনি প্রকারটি উল্লেখ করতে পারেন। এটি যে কোনও ধরণের সেটের জন্য কাজ করবে।


3

এটি সম্ভব হতে পারে যে সংকলক জাভা বাইট কোডে সেট (পূর্ণসংখ্যার) সেট (অবজেক্ট) তে অনুবাদ করে। যদি এটি হয় তবে সেট (পূর্ণসংখ্যা) কেবল সিনট্যাক্স পরীক্ষার জন্য সংকলন পর্যায়ে ব্যবহৃত হবে।


5
এটি প্রযুক্তিগতভাবে কেবল কাঁচা টাইপ Set। বেনি কোডগুলিতে জেনেরিক্সের অস্তিত্ব নেই, তারা কাস্টিংয়ের জন্য সিনট্যাকটিক চিনি এবং সংকলন-সময় ধরণের সুরক্ষা সরবরাহ করে।
আন্দ্রেজ ডয়েল

1

এই জাতীয়: Continuable<T> callAsync(Callable<T> code) {....} এবং Continuable<Continuable<T>> callAsync(Callable<Continuable<T>> veryAsyncCode) {...} তারা সংজ্ঞা সংকলনের জন্য হয়ে যায় 2 সংজ্ঞা Continuable<> callAsync(Callable<> veryAsyncCode) {...}

টাইপ ইরেজরের আক্ষরিক অর্থ জেনেরিকস থেকে টাইপ আর্গুমেন্টের তথ্য মুছে ফেলা। এটি খুব বিরক্তিকর, তবে এটি এমন একটি সীমাবদ্ধতা যা জাভাতে কিছু সময়ের জন্য থাকবে। কনস্ট্রাক্টর কেসের ক্ষেত্রে খুব বেশি কিছু করা যায় না, উদাহরণস্বরূপ কনস্ট্রাক্টরের বিভিন্ন পরামিতিগুলির সাথে বিশেষত 2 টি নতুন সাবক্ল্যাসেস। বা পরিবর্তে আরম্ভের পদ্ধতিগুলি ব্যবহার করুন ... (ভার্চুয়াল কনস্ট্রাক্টর?) বিভিন্ন নামের সাথে ...

অনুরূপ অপারেশন পদ্ধতির জন্য নাম পরিবর্তন করা যেমন পছন্দ করে

class Test{
   void addIntegers(Set<Integer> ii){}
   void addStrings(Set<String> ss){}
}

বা আরও কিছু বর্ণনামূলক নাম সহ ওইউ ক্ষেত্রে স্ব-ডকুমেন্টিং, যেমন addNamesএবং এই addIndexesজাতীয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.