জাভা 8-এ যখন আমাদের ইতিমধ্যে বিমূর্ত ক্লাস ছিল তখন ডিফল্ট এবং স্থিতিশীল পদ্ধতিগুলিকে কেন ইন্টারফেসে যুক্ত করা হয়েছিল?


99

জাভা 8-এ, ইন্টারফেসগুলি বাস্তবায়িত পদ্ধতি, স্থিতিশীল পদ্ধতি এবং তথাকথিত "ডিফল্ট" পদ্ধতিগুলি (যা প্রয়োগকারী শ্রেণিগুলিকে ওভাররাইড করার প্রয়োজন হয় না) ধারণ করতে পারে।

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

  1. স্থির পদ্ধতি ইন্টারফেসের সাথে সম্পর্কিত নয়। তারা ইউটিলিটি ক্লাসের অন্তর্গত।
  2. ইন্টারফেসে "ডিফল্ট" পদ্ধতিগুলির অনুমতি দেওয়া উচিত ছিল না। আপনি এই উদ্দেশ্যে সর্বদা একটি বিমূর্ত শ্রেণি ব্যবহার করতে পারেন।

সংক্ষেপে:

জাভা 8 এর আগে:

  • স্ট্যাটিক এবং ডিফল্ট পদ্ধতি সরবরাহের জন্য আপনি বিমূর্ত এবং নিয়মিত ক্লাস ব্যবহার করতে পারেন। ইন্টারফেসের ভূমিকা পরিষ্কার।
  • একটি ইন্টারফেসের সমস্ত পদ্ধতি ক্লাস প্রয়োগ করে ওভাররাইড করা উচিত।
  • সমস্ত বাস্তবায়ন সংশোধন না করে আপনি কোনও ইন্টারফেসে একটি নতুন পদ্ধতি যুক্ত করতে পারবেন না, তবে এটি আসলে একটি ভাল জিনিস।

জাভা 8 পরে:

  • একটি ইন্টারফেস এবং একটি বিমূর্ত শ্রেণীর (একাধিক উত্তরাধিকার ব্যতীত) মধ্যে কার্যত কোনও পার্থক্য নেই। আসলে আপনি একটি ইন্টারফেস দিয়ে একটি নিয়মিত ক্লাস অনুকরণ করতে পারেন।
  • বাস্তবায়নগুলি প্রোগ্রামিং করার সময় প্রোগ্রামাররা ডিফল্ট পদ্ধতিগুলিকে ওভাররাইড করতে ভুলে যেতে পারে।
  • একটি শ্রেণি একই স্বাক্ষর সহ একটি ডিফল্ট পদ্ধতিযুক্ত দুটি বা আরও বেশি ইন্টারফেস প্রয়োগ করার চেষ্টা করে তবে একটি সংকলন ত্রুটি রয়েছে।
  • একটি ইন্টারফেসে একটি ডিফল্ট পদ্ধতি যুক্ত করে প্রতিটি প্রয়োগকারী শ্রেণি স্বয়ংক্রিয়ভাবে এই আচরণের উত্তরাধিকার সূত্রে প্রাপ্ত হয়। এই ক্লাসগুলির কয়েকটি হয়ত সেই নতুন কার্যকারিতাটি মাথায় রেখে তৈরি করা হয়নি এবং এটি সমস্যার কারণ হতে পারে। উদাহরণস্বরূপ, যদি কেউ কোনও default void foo()ইন্টারফেসে একটি নতুন ডিফল্ট পদ্ধতি যুক্ত করে Ix, তবে শ্রেণিটি একই স্বাক্ষর সহ একটি ব্যক্তিগত পদ্ধতি Cxপ্রয়োগ করে Ixএবং fooসংকলন করে না।

এই ধরনের বড় পরিবর্তনের মূল কারণগুলি কী এবং তারা কোন নতুন সুবিধা (যদি থাকে) যোগ করে?


30
বোনাস প্রশ্ন: কেন তারা ক্লাসের পরিবর্তে একাধিক উত্তরাধিকার প্রবর্তন করেনি?

2
স্থির পদ্ধতি ইন্টারফেসের সাথে সম্পর্কিত নয়। তারা ইউটিলিটি ক্লাসের অন্তর্গত। না তারা @Deprecatedবিভাগে অন্তর্ভুক্ত! অজ্ঞতা এবং অলসতার কারণে স্থির পদ্ধতি জাভাতে সর্বাধিক আপত্তিজনক নির্মাণ const প্রচুর স্থিতিশীল পদ্ধতিগুলির অর্থ সাধারণত অযোগ্য প্রোগ্রামার মানে, একাধিক মাত্রার ক্রম সংযোজন বৃদ্ধি এবং ইউনিট পরীক্ষা এবং রিফ্যাক্টরের একটি দুঃস্বপ্ন যখন আপনি বুঝতে পারেন যে তারা কেন খারাপ ধারণা!

11
@ জারোডরোবারসন "ইউনিট টেস্ট এবং রিফ্যাক্টরের একটি দুঃস্বপ্ন যখন আপনি বুঝতে পারেন যে তারা কেন খারাপ ধারণা?" আমি কখনই এটি ভাবিনি এবং আমি এটি সম্পর্কে আরও জানতে চাই।
জল

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

1
আপনি বিদ্যমান ইন্টারফেসে পদ্ধতিটি যুক্ত করতে চান, জাভা 8 এর আগে জটিল বা প্রায় সম্ভব ছিল না এখন আপনি কেবল এটি ডিফল্ট পদ্ধতি হিসাবে যুক্ত করতে পারেন।
ভিডিএক্স

উত্তর:


59

ডিফল্ট পদ্ধতিগুলির জন্য একটি উত্তম প্রেরণাদায়ক উদাহরণ জাভা স্ট্যান্ডার্ড লাইব্রেরিতে রয়েছে, যেখানে এখন আপনার রয়েছে

list.sort(ordering);

পরিবর্তে

Collections.sort(list, ordering);

আমি মনে করি না যে তারা এটি করতে পারত অন্যথায় একাধিক অভিন্ন বাস্তবায়ন ছাড়াই List.sort


19
সি # এক্সটেনশন পদ্ধতিগুলির মাধ্যমে এই সমস্যাটি কাটিয়ে উঠেছে।
রবার্ট হার্ভে

5
এবং এটি একটি লিঙ্কযুক্ত তালিকাকে একটি ও (1) অতিরিক্ত স্থান এবং ও (এন লগ এন) সময় সংশ্লেষ ব্যবহার করার অনুমতি দেয়, কারণ লিঙ্কযুক্ত তালিকাগুলি স্থানটিতে একত্রীকরণ করা যায়, জাভা 7 এ এটি একটি বাহ্যিক অ্যারেতে ফেলে দেয় এবং পরে এটি সাজান
র‌্যাচেট ফ্রিক

5
এই কাগজটি আমি খুঁজে পেয়েছি যেখানে গোয়েজ সমস্যাটি ব্যাখ্যা করে। সুতরাং আমি এই উত্তরটি আপাতত সমাধান হিসাবে চিহ্নিত করব।
মিস্টার স্মিথ

1
@ রবার্টহারভে: দু'শ মিলিয়ন-আইটেমের তালিকা তৈরি করুন <বাইটায়> এগুলিতে IEnumerable<Byte>.Appendযোগদানের জন্য ব্যবহার করুন এবং তারপরে ফোন করুন Count, তারপরে আমাকে বলুন কীভাবে এক্সটেনশন পদ্ধতিগুলি সমস্যার সমাধান করে। যদি CountIsKnownএবং এর Countসদস্য হন তবে নির্বাচনী উপাদান সংগ্রহগুলি যদি করত তবে IEnumerable<T>সেখান থেকে প্রত্যাবর্তন Appendবিজ্ঞাপন দিতে পারত CountIsKnown, তবে এই জাতীয় পদ্ধতি ছাড়া এটি সম্ভব নয়।
সুপারক্যাট

6
@ সুপের্যাট: আপনি কী বলছেন তা আমার সামান্যতম ধারণাও নেই।
রবার্ট হার্ভে

48

সঠিক উত্তরটি আসলে জাভা ডকুমেন্টেশনে পাওয়া গেছে , যা বলে:

[d] ইফল্ট পদ্ধতিগুলি আপনাকে আপনার লাইব্রেরির ইন্টারফেসগুলিতে নতুন কার্যকারিতা যুক্ত করতে এবং সেই ইন্টারফেসগুলির পুরানো সংস্করণগুলির জন্য লিখিত কোডের সাথে বাইনারি সামঞ্জস্যতা নিশ্চিত করতে সক্ষম করে।

এটি জাভাতে দীর্ঘস্থায়ী ব্যথার উত্স হয়ে দাঁড়িয়েছে, কারণ ইন্টারফেসগুলি জনসমক্ষে প্রকাশিত হওয়ার পরে এটি বিকশিত হওয়া অসম্ভব বলে মনে হয়েছিল। (ডকুমেন্টেশনের বিষয়বস্তু সেই কাগজের সাথে সম্পর্কিত যা আপনি একটি মন্তব্যে লিঙ্ক করেছেন: ভার্চুয়াল এক্সটেনশন পদ্ধতিগুলির মাধ্যমে ইন্টারফেস বিবর্তন ।) তদুপরি, নতুন বৈশিষ্ট্যগুলি (যেমন ল্যাম্বডাস এবং নতুন স্ট্রিম এপিআই) দ্রুত গ্রহণ কেবলমাত্র প্রসারিত করেই করা যেতে পারে বিদ্যমান সংগ্রহ ইন্টারফেস এবং ডিফল্ট বাস্তবায়ন সরবরাহ করে। বাইনারি সামঞ্জস্যতা ভঙ্গ করা বা নতুন এপিআইগুলি প্রবর্তনের অর্থ জাভা 8 এর সবচেয়ে গুরুত্বপূর্ণ বৈশিষ্ট্যগুলি সাধারণ ব্যবহারে আসার আগে বেশ কয়েক বছর কেটে যাবে।

ইন্টারফেসে স্থির পদ্ধতিগুলি অনুমোদনের কারণ ডকুমেন্টেশনের মাধ্যমে আবার প্রকাশিত হয়েছে: [টি] আপনার জন্য আপনার লাইব্রেরিতে সহায়ক পদ্ধতিগুলি পরিচালনা করা সহজ করে তোলে; আপনি পৃথক শ্রেণীর পরিবর্তে একই ইন্টারফেসের একটি ইন্টারফেসের সাথে নির্দিষ্ট স্ট্যাটিক পদ্ধতি রাখতে পারেন। অন্য কথায়, স্ট্যাটিক ইউটিলিটি ক্লাসগুলি java.util.Collectionsএখন (শেষ পর্যন্ত) একটি অ্যান্টি-প্যাটার্ন হিসাবে বিবেচিত হতে পারে, সাধারণভাবে (অবশ্যই সর্বদা নয় )। আমার ধারণা হ'ল ভার্চুয়াল এক্সটেনশন পদ্ধতিগুলি প্রয়োগ করা হলে এই আচরণের জন্য সমর্থন যোগ করা তুচ্ছ ছিল, অন্যথায় এটি সম্ভবত না করা হত।

অনুরূপ নোটে, এই নতুন বৈশিষ্ট্যগুলি কীভাবে উপকারী হতে পারে তার একটি উদাহরণ হ'ল সম্প্রতি এমন একটি শ্রেণি বিবেচনা করা, যা আমাকে সম্প্রতি বিরক্ত করেছে java.util.UUID,। এটি ইউআইডি প্রকার 1, 2 বা 5 এর জন্য সত্যই সমর্থন সরবরাহ করে না এবং এটি করার জন্য এটি সহজেই সংশোধন করা যায় না। এটি পূর্বনির্ধারিত এলোমেলো জেনারেটরের সাথে আটকেও রয়েছে যা ওভাররাইড করা যায় না। অসমর্থিত ইউআইডি জাতীয় ধরণের কোড প্রয়োগের জন্য ইন্টারফেসের পরিবর্তে তৃতীয় পক্ষের এপিআইয়ের উপর সরাসরি নির্ভরতা প্রয়োজন, না হয় রূপান্তর কোডের রক্ষণাবেক্ষণ এবং এর সাথে যেতে অতিরিক্ত আবর্জনা সংগ্রহের ব্যয়। স্থিতিশীল পদ্ধতি দ্বারা, UUIDপরিবর্তে একটি ইন্টারফেস হিসাবে সংজ্ঞায়িত করা যেতে পারে, অনুপস্থিত টুকরাগুলির সত্যিকারের তৃতীয় পক্ষের বাস্তবায়নের অনুমতি দেওয়া। (যদি UUIDপ্রাথমিকভাবে একটি ইন্টারফেস হিসাবে সংজ্ঞায়িত করা হয় তবে আমাদের সম্ভবত কিছুটা ক্লানকি থাকতে হবেUuidUtil স্থিতিশীল পদ্ধতি সহ ক্লাস, যা অত্যন্ত ভয়ঙ্করও হবে)

এটি বলা ঠিক নয় যে [টি] এখানে একটি ইন্টারফেস এবং বিমূর্ত শ্রেণীর মধ্যে কার্যত কোনও পার্থক্য নেই , কারণ অ্যাবস্ট্রাক্ট ক্লাসগুলির রাষ্ট্র থাকতে পারে (যা ক্ষেত্রগুলি ঘোষণা করতে পারে) যখন ইন্টারফেসগুলি পারে না। এটি একাধিক উত্তরাধিকার এমনকি মিক্সিন-স্টাইলের উত্তরাধিকারের সমতুল্য নয়। যথাযথ মিক্সিনগুলির (যেমন গ্রোভির ২.৩ এর বৈশিষ্ট্যগুলি ) স্থিতিতে অ্যাক্সেস রয়েছে। (গ্রোভি স্থিতিশীল এক্সটেনশন পদ্ধতিগুলিও সমর্থন করে))

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


1
(অর্থাত আরও ফলো-আপ আমার শেষ অনুচ্ছেদ এর জন্য ইন্টারফেসে চুক্তি বলবত করে না ), এটা ইশারা মূল্য যে defaultপদ্ধতি ওভাররাইড করতে পারবে না equals, hashCodeএবং toString। কেন এই অননুমোদিত একটি খুব তথ্যপূর্ণ খরচ / বেনিফিট বিশ্লেষণ এখানে পাওয়া যাবে: mail.openjdk.java.net/pipermail/lambda-dev/2013-March/...
ngreen

এটি খুব খারাপ যে জাভাতে কেবল একটি একক ভার্চুয়াল equalsএবং একক hashCodeপদ্ধতি রয়েছে যেহেতু দুটি ভিন্ন ধরণের সাম্য আছে যা সংগ্রহের পরীক্ষার প্রয়োজন হতে পারে এবং যে আইটেমগুলি একাধিক ইন্টারফেস বাস্তবায়িত করবে সেগুলি পরস্পর বিরোধী চুক্তির প্রয়োজনীয়তার সাথে আটকে থাকতে পারে। hashMapকীগুলি পরিবর্তিত হয় না এমন তালিকাগুলি ব্যবহার করতে সক্ষম হওয়ায় সহায়ক, তবে এমনও সময় রয়েছে যখন hashMapবর্তমানের অবস্থার চেয়ে সমানতার ভিত্তিতে জিনিসগুলির সাথে ম্যাচ করা সংগ্রহগুলি সংরক্ষণ করতে সহায়ক হবে [সমতা মেলানো রাষ্ট্র এবং অপরিবর্তনীয়তা বোঝায় ] ।
সুপারক্যাট

ঠিক আছে, জাভা সাজ্টের তুলনাকারী এবং তুলনামূলক ইন্টারফেসগুলির সাথে একটি কার্যকারিতা রয়েছে। তবে সেগুলি কদর্য ধরনের I
ngreen

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

ওহ হ্যাঁ, আমি তুলকের যন্ত্রণা পেয়েছি। আমি একটি গাছের কাঠামোর উপর কাজ করছি যা সাধারণ হওয়া উচিত তবে এটি তুলনামূলক সঠিকভাবে পাওয়া খুব শক্ত কারণ। সমস্যাটি দূরে সরিয়ে দিতে আমি সম্ভবত একটি কাস্টম ট্রি ক্লাস লিখছি।
ngreen

44

কারণ আপনি কেবল এক শ্রেণির উত্তরাধিকারী হতে পারেন। যদি আপনি দুটি ইন্টারফেস পেয়ে থাকেন যার বাস্তবায়নগুলি এমন জটিল যে আপনার একটি বিমূর্ত বেস শ্রেণীর প্রয়োজন, তবে এই দুটি ইন্টারফেস অনুশীলনে পারস্পরিক একচেটিয়া।

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


ইন্টারফেসে বাস্তবায়ন সরবরাহ করতে সক্ষম হওয়া কেন একটি অনুপ্রেরণামূলক উদাহরণ হিসাবে, এই স্ট্যাক ইন্টারফেসটি বিবেচনা করুন:

public interface Stack<T> {
    boolean isEmpty();

    T pop() throws EmptyException;
 }

গ্যারান্টি দেওয়ার কোনও উপায় নেই যে যখন কেউ ইন্টারফেসটি প্রয়োগ করে, popস্ট্যাকটি খালি থাকলে একটি ব্যতিক্রম ছুঁড়ে দেবে। আমরা popদুটি পদ্ধতির মধ্যে বিভক্ত হয়ে এই নিয়মটি প্রয়োগ করতে পারি : একটি public finalপদ্ধতি যা চুক্তি কার্যকর করে এবং এমন একটি protected abstractপদ্ধতি যা আসল পপিং সম্পাদন করে।

public abstract class Stack<T> {
    public abstract boolean isEmpty();

    protected abstract T pop_implementation();

    public final T pop() throws EmptyException {
        if (isEmpty()) {
            throw new EmptyException();
        else {
            return pop_implementation();
        }
    }
 }

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

ইন্টারফেসে পদ্ধতি যুক্ত করার ক্ষেত্রে জাভা 8-এর পদ্ধতি চূড়ান্ত পদ্ধতি বা সুরক্ষিত বিমূর্ত পদ্ধতি যুক্ত করার অনুমতি দেয় কিনা তা আমি নিশ্চিত নই, তবে আমি জানি ডি ভাষা এটির অনুমতি দেয় এবং চুক্তি অনুসারে ডিজাইনের জন্য স্থানীয় সমর্থন সরবরাহ করেpopচূড়ান্ত হওয়ার পর থেকে এই কৌশলটিতে কোনও বিপদ নেই , তাই কোনও বাস্তবায়নকারী শ্রেণি এটিকে ওভাররাইড করতে পারে না।

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

অধিকন্তু,

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

আপনি একে একে ইন্টারফেসে ক্ষেত্রগুলি ঘোষণা করতে পারবেন না এটি একেবারেই সত্য নয়। আপনি কোনও ইন্টারফেসে যে পদ্ধতি লিখেছেন তা প্রয়োগের কোনও বিবরণে নির্ভর করতে পারে না।


ইন্টারফেসে স্থির পদ্ধতির পক্ষে উদাহরণ হিসাবে , জাভা এপিআইতে সংগ্রহের মতো ইউটিলিটি ক্লাস বিবেচনা করুন । এই শ্রেণিটি কেবলমাত্র বিদ্যমান কারণ এই স্থির পদ্ধতিগুলি তাদের নিজ নিজ ইন্টারফেসে ঘোষণা করা যায় না। ইন্টারফেসে Collections.unmodifiableListঠিক ততই ঘোষণা Listকরা যেত এবং এটি খুঁজে পাওয়া আরও সহজ হত।


4
পাল্টা যুক্তি: যেহেতু স্থির পদ্ধতিগুলি যথাযথভাবে লিখিত হয় তবে তা স্বয়ংসম্পূর্ণ, তারা পৃথক স্ট্যাটিক শ্রেণিতে আরও বোধগম্য হয় যেখানে তারা শ্রেণীর নাম দ্বারা সংগ্রহ এবং শ্রেণিবদ্ধ করা যেতে পারে এবং একটি ইন্টারফেসে কম সংজ্ঞায়িত হয়, যেখানে এগুলি মূলত একটি সুবিধা convenience যা বস্তুকে স্থিতিশীল অবস্থা ধরে রাখা বা পার্শ্ব প্রতিক্রিয়া সৃষ্টি করার মতো স্থিতিগুলিকে আমন্ত্রণ জানায়, স্থির পদ্ধতিগুলিকে অযোগ্য করে তোলে।
রবার্ট হার্ভে

3
@ রবার্টহার্ভে আপনার স্থির পদ্ধতিটি যদি ক্লাসে থাকে তবে আপনাকে সমান নির্বোধ কাজ করতে বাধা দেওয়ার কী আছে? এছাড়াও, যে ইন্টারফেসের পদ্ধতিটির জন্য কোনও রাজ্যের প্রয়োজন হয় না। আপনি কেবল একটি চুক্তি কার্যকর করার চেষ্টা করছেন। মনে করুন আপনি একটি Stackইন্টারফেস পেয়েছেন এবং আপনি নিশ্চিত করতে চান যে যখন popখালি স্ট্যাক দিয়ে ডাকা হবে তখন একটি ব্যতিক্রম ছুঁড়ে দেওয়া হবে। বিমূর্ত পদ্ধতি দেওয়া হয়েছে boolean isEmpty()এবং protected T pop_impl()আপনি প্রয়োগ করতে পারেন final T pop() { isEmpty()) throw PopException(); else return pop_impl(); }এটি সমস্ত প্রয়োগকারীদের উপর চুক্তি কার্যকর করে।
ডোভাল

কিসের অপেক্ষা? একটি স্ট্যাক ধাক্কা এবং পপ পদ্ধতি না হতে যাচ্ছে static
রবার্ট হার্ভে

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

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

2

সম্ভবত অভিপ্রায়টি নির্ভরতার মাধ্যমে স্থির তথ্য বা কার্যকারিতা ইনজেকশনের প্রয়োজনের পরিবর্তে মিক্সিন ক্লাস তৈরির দক্ষতা সরবরাহ করা ছিল ।

এই ধারণাটি কীভাবে আপনি সি # তে এক্সটেনশান পদ্ধতি ব্যবহার করতে পারবেন ইন্টারফেসগুলিতে প্রয়োগিত কার্যকারিতা যুক্ত করতে to


1
এক্সটেনশন পদ্ধতিগুলি ইন্টারফেসগুলিতে কার্যকারিতা যুক্ত করে না। সুবিধাজনক list.sort(ordering);ফর্মটি ব্যবহার করে কোনও শ্রেণিতে স্থির পদ্ধতিগুলি কল করার জন্য এক্সটেনশন পদ্ধতিগুলি কেবল সিনট্যাকটিক চিনি ।
রবার্ট হার্ভে

আপনি যদি IEnumerableসি # তে ইন্টারফেসের দিকে তাকান , আপনি দেখতে পারেন যে কীভাবে সেই ইন্টারফেসে এক্সটেনশন পদ্ধতিগুলি প্রয়োগ করা হয় (যেমন LINQ to Objectsহয়) প্রয়োগ করে এমন প্রতিটি শ্রেণীর জন্য কার্যকারিতা যুক্ত করে IEnumerable। এটিই আমি কার্যকারিতা যুক্ত করে বোঝাতে চাইছি।
rae1

2
এটি এক্সটেনশন পদ্ধতি সম্পর্কে দুর্দান্ত জিনিস; তারা এই ধারণাটি দেয় যে আপনি কোনও শ্রেণি বা ইন্টারফেসে কার্যকারিতার উপর ঝুঁকছেন। একটি ক্লাসে আসল পদ্ধতি যুক্ত করার সাথে কেবল এটি বিভ্রান্ত করবেন না; শ্রেণি পদ্ধতিতে কোনও অবজেক্টের ব্যক্তিগত সদস্যদের অ্যাক্সেস থাকে, এক্সটেনশন পদ্ধতিগুলি হয় না (যেহেতু তারা স্ট্যাটিক পদ্ধতিগুলি কল করার সত্যিই অন্য উপায়)।
রবার্ট হার্ভে

2
হুবহু, এবং সে কারণেই আমি জাভাতে একটি ইন্টারফেসে স্থির বা ডিফল্ট পদ্ধতিতে কিছু সম্পর্ক দেখতে পাচ্ছি; প্রয়োগটি ইন্টারফেসে যা উপলব্ধ তা ক্লাসের নয়, এর উপর ভিত্তি করে।
rae1

1

দুটি defaultপদ্ধতিতে আমি পদ্ধতিগুলিতে দেখি (কিছু ব্যবহারের ক্ষেত্রে উভয় উদ্দেশ্যই কার্যকর হয়):

  1. সিনট্যাক্স চিনি। একটি ইউটিলিটি ক্লাস সেই লক্ষ্যে কাজ করতে পারে তবে উদাহরণ পদ্ধতিগুলি আরও ভাল।
  2. একটি বিদ্যমান ইন্টারফেস এক্সটেনশন। বাস্তবায়ন জেনেরিক তবে কখনও কখনও অদক্ষ।

যদি এটি কেবল দ্বিতীয় উদ্দেশ্যটি সম্পর্কে ছিল তবে আপনি এটি ব্র্যান্ডের নতুন ইন্টারফেসের মতো দেখতে পাবেন না Predicate। সমস্ত @FunctionalInterfaceবর্ণিত ইন্টারফেসের ঠিক একটি বিমূর্ত পদ্ধতি থাকা প্রয়োজন যাতে একটি ল্যাম্বডা এটি প্রয়োগ করতে পারে। যোগ করা হয়েছে defaultমত পদ্ধতি and, or, negateশুধু ইউটিলিটি আছে, এবং আপনি তাদের ওভাররাইড করতে অনুমিত হয় না। তবে, কখনও কখনও স্থির পদ্ধতি আরও ভাল করতে পারে

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


staticপদ্ধতিগুলি হিসাবে , আমি অনুমান করি যে অন্যরা এটি বেশ ভালভাবে কভার করেছে: এটি ইন্টারফেসটিকে তার নিজস্ব ইউটিলিটি শ্রেণিতে পরিণত করার অনুমতি দেয়। আমরা Collectionsজাভা ভবিষ্যতে পরিত্রাণ পেতে পারে ? Set.empty()দোলা হবে

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