একাধিক উত্তরাধিকার নিয়ে সঠিক সমস্যাটি কী?


121

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

একাধিক উত্তরাধিকার নিয়ে কী হয়েছে? কোন কংক্রিট নমুনা আছে?


54
আমি কেবল উল্লেখ করব যে নিজেকে ঝুলানোর জন্য যথেষ্ট দড়ি দেওয়ার জন্য সি ++ দুর্দান্ত great
স্লোগান দিন

1
একই সমস্যাগুলির সাথে সম্বোধন করে (এবং, আইএমএইচওও সমাধান করে) একাধিক উত্তরাধিকারের বিকল্পের জন্য, বৈশিষ্ট্যগুলি দেখুন ( iam.unibe.ch/~scg/Research/Traits )
বেভান

52
আমি ভেবেছিলাম সি ++ আপনাকে পায়ে গুলি করতে যথেষ্ট দড়ি দেয় gives
কিথবি

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

উত্তর:


86

সর্বাধিক সুস্পষ্ট সমস্যা হ'ল ফাংশন ওভাররাইডিং।

আসুন বলি দুটি ক্লাস রয়েছে Aএবং Bউভয়ই একটি পদ্ধতির সংজ্ঞা দেয় doSomething। এখন আপনি একটি থার্ড ক্লাস সংজ্ঞায়িত Cউভয় থেকে, যা উত্তরাধিকারী Aএবং B, কিন্তু আপনি ওভাররাইড না doSomethingপদ্ধতি।

সংকলক যখন এই কোডটি বীজ করে ...

C c = new C();
c.doSomething();

... পদ্ধতির কোন প্রয়োগটি ব্যবহার করা উচিত? আরও কোনও ব্যাখ্যা ছাড়াই সংকলকটির পক্ষে অস্পষ্টতা সমাধান করা অসম্ভব।

ওভাররাইড ছাড়াও, একাধিক উত্তরাধিকারের সাথে অন্য বড় সমস্যা হ'ল মেমরির দৈহিক বস্তুর বিন্যাস।

সি ++ এবং জাভা এবং সি # এর মতো ভাষা প্রতিটি ধরণের অবজেক্টের জন্য স্থির ঠিকানা-ভিত্তিক বিন্যাস তৈরি করে। এটার মতো কিছু:

class A:
    at offset 0 ... "abc" ... 4 byte int field
    at offset 4 ... "xyz" ... 8 byte double field
    at offset 12 ... "speak" ... 4 byte function pointer

class B:
    at offset 0 ... "foo" ... 2 byte short field
    at offset 2 ... 2 bytes of alignment padding
    at offset 4 ... "bar" ... 4 byte array pointer
    at offset 8 ... "baz" ... 4 byte function pointer

সংকলক যখন মেশিন কোড উত্পন্ন করে (বা বাইটকোড), এটি প্রতিটি পদ্ধতি বা ক্ষেত্র অ্যাক্সেস করতে সেই সংখ্যাসূচক অফসেটগুলি ব্যবহার করে।

একাধিক উত্তরাধিকার এটিকে খুব কৃপণ করে তোলে।

বর্গ তাহলে Cউভয় থেকে উত্তরাধিকারী Aএবং B, কম্পাইলার ডেটা বিন্যাস ব্যবহার করার সিদ্ধান্ত নেন হয়েছে ABঅর্ডার বা BAঅর্ডার।

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

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

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


62
এহম, পাইথন এমআই সমর্থন করে
নেমানজা ত্রিফুনোভিচ

26
এগুলি খুব দৃinc়প্রত্যয়ী যুক্তি নয় - স্থির বিন্যাস জিনিসটি বেশিরভাগ ভাষায় মোটেই জটিল নয়; সি ++ এ এটি মুশকিল কারণ মেমরিটি অস্বচ্ছ নয় এবং এইভাবে আপনি পয়েন্টার গাণিতিক অনুমানের সাথে কিছুটা অসুবিধায় পড়তে পারেন। যে ভাষাগুলিতে শ্রেণীর সংজ্ঞা স্থির থাকে (যেমন জাভা, সি # এবং সি ++ তে), একাধিক উত্তরাধিকার নাম সংঘর্ষের সময় সংকলন নিষিদ্ধ করা যেতে পারে (এবং সি # এটি কোনওভাবে ইন্টারফেস সহ করে!)।
ইমন নের্বোন

10
ওপি কেবল বিষয়গুলি বুঝতে চেয়েছিল এবং আমি ব্যক্তিগতভাবে বিষয়টি নিয়ে সম্পাদকীয় না করে সেগুলি ব্যাখ্যা করেছি। আমি কেবল বলেছি যে ভাষা ডিজাইনার এবং সংকলক বাস্তবায়নকারীরা "সম্ভবত সুবিধাটি ব্যয়ের জন্য মূল্যবান বলে মনে করেন না"।
বেনজিসমথ

12
" সর্বাধিক সুস্পষ্ট সমস্যা ফাংশন ওভাররাইডিংয়ের সাথে। " ফাংশন ওভাররাইডিংয়ের সাথে এর কোনও যোগসূত্র নেই। এটি একটি সাধারণ অস্পষ্টতা সমস্যা।
কৌতূহলী

10
পাইথন এমআই সমর্থন করে যেহেতু এই উত্তরে গুইডো এবং পাইথন সম্পর্কে কিছু ভুল তথ্য রয়েছে। "আমি স্থির করেছিলাম যে যতক্ষণ আমি উত্তরাধিকারকে সমর্থন করব, আমি পাশাপাশি একাধিক উত্তরাধিকারের একটি সহজ-মনের সংস্করণকেও সমর্থন করতে পারি" " - গাইডো ভ্যান রোসম পাইথন-history.blogspot.com/2009/02/… - এছাড়াও, অস্পষ্টতা রেজোলিউশন সংকলকগুলিতে মোটামুটি সাধারণ (ভেরিয়েবলগুলি স্থানীয়ভাবে ব্লক হতে পারে, ফাংশন থেকে স্থানীয় হতে পারে, স্থানীয়ভাবে আটকানো ফাংশন, অবজেক্ট সদস্য, শ্রেণীর সদস্য, গ্লোবাল ইত্যাদি), আমি দেখতে পাচ্ছি না যে কীভাবে একটি অতিরিক্ত সুযোগ একটি পার্থক্য তৈরি করবে।
মার্কাস

46

আপনি যে সমস্যার কথা বলবেন, সেগুলি সমাধান করা আসলে খুব কঠিন নয়। আসলে যেমন আইফেল পুরোপুরি ভাল করে! (এবং স্বেচ্ছাসেবী পছন্দ বা যা কিছু প্রবর্তন না করে)

উদাহরণস্বরূপ, যদি আপনি A এবং B থেকে উত্তরাধিকারী হন, উভয়ই পদ্ধতিতে foo () থাকে তবে অবশ্যই আপনি আপনার ক্লাস সিতে স্বেচ্ছাসেবী পছন্দ করতে চান না A এবং B. উভয়ই উত্তরাধিকার সূত্রে আপনার হয় হয় পুনরায় সংজ্ঞা দিতে হবে সুতরাং এটি স্পষ্ট হবে কী হবে c.foo () বলা হলে ব্যবহৃত হয় বা অন্যথায় আপনাকে সি এর একটি পদ্ধতির নাম পরিবর্তন করতে হবে (এটি বার () হয়ে যেতে পারে)

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


26
আমি রাজী. লোকেরা এমআইকে ঘৃণা করার মূল কারণটি জাভাস্ক্রিপ্ট বা স্থির টাইপিংয়ের সাথে একই: বেশিরভাগ লোকেরা এটির খুব খারাপ প্রয়োগ কখনওই ব্যবহার করেছে - বা এটি খুব খারাপ ব্যবহার করেছে। সি ++ দ্বারা এমআই বিচার করা পিএইচপি দ্বারা ওওপি বিচার করার বা পিন্টোসের দ্বারা অটোমোবাইলগুলি বিচার করার মতো।
জার্গ ডব্লু মিটাগ

2
@ কুরিয়াসগুয়ে: এমআই আরও অনেক জটিলতার উদ্বিগ্ন হ'ল সি ++ এর অনেকগুলি "বৈশিষ্ট্য" এর মতো। এটি দ্ব্যর্থহীন হওয়ায় এটি কাজ করা বা ডিবাগ করা সহজ করে না। এই শৃঙ্খলাটি মুছে ফেলা হচ্ছে যেহেতু এটি বিষয়বস্তুতে চলেছে এবং আপনি এটিকে যাইহোক উড়িয়ে দিয়েছেন।
গুয়ানতে

4
@ গুভান্তে যে কোনও ভাষায় এমআইয়ের একমাত্র সমস্যা শিট্টি প্রোগ্রামাররা এই ভেবে যে তারা টিউটোরিয়ালটি পড়তে পারে এবং হঠাৎ কোনও ভাষা জানতে পারে।
মাইলস রাউট

2
আমি তর্ক করব যে ভাষার বৈশিষ্ট্যগুলি কেবল কোডিংয়ের সময় হ্রাস করার জন্য নয়। তারা কোনও ভাষার ভাব প্রকাশ এবং ক্রিয়াকলাপ বাড়ানোর বিষয়ে about
মাইলস রাউট

4
এছাড়াও, যখন বুদ্ধিমানরা ভুলভাবে এটি ব্যবহার করে তখন এমআই থেকে বাগগুলি ঘটে।
মাইলস রাউথ

27

হীরা সমস্যা :

একটি অস্পষ্টতা দেখা দেয় যখন দুটি ক্লাস বি এবং সি এ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়, এবং বর্গ ডি বি এবং সি উভয়েরই উত্তরাধিকার সূত্রে প্রাপ্ত হয়, যদি এ-তে কোনও পদ্ধতি আছে যে বি এবং সি ওভাররাইড করেছে এবং ডি এটিকে ওভাররাইড করে না, তবে কোন সংস্করণটি ডিটি উত্তরাধিকার সূত্রে বি: বা সি এর?

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


4
যার সমাধান রয়েছে ভার্চুয়াল উত্তরাধিকার হিসাবে। আপনি যদি এটি ভুল করেন তবে এটি কেবল একটি সমস্যা।
ইয়ান গোল্ডবি

1
@ ইয়ান গোল্ডবি: ভার্চুয়াল উত্তরাধিকার হ'ল সমস্যাটির সমাধানের একটি প্রক্রিয়া, যদি কারও কাছে পরিচয় সংরক্ষণের উত্সাহ এবং ঝুঁকির অনুমতি প্রয়োজন হয় না যার থেকে উদাহরণস্বরূপ উদ্ভূত হয় বা যার পরিবর্তে এটি পরিবর্তনযোগ্য । প্রদত্ত এক্স: বি; ওয়াই: বি; এবং জেড: এক্স, ওয়াই; ধরুন সামজারড হ'ল জেডের উদাহরণ virtual প্রদত্ত হয়, এক একটি ঝরঝরে এবং আপকাস্ট মাধ্যমে অন্য পেতে পারে, কিন্তু যদি একটি আছে someZএবং এটি করতে চান Objectএবং তারপর কাস্ট করতে চান B? Bএটি কোনটি পাবে?
সুপারক্যাট

2
@ সুপের্যাট সম্ভবত, তবে এর মতো সমস্যাগুলি মূলত তাত্ত্বিক এবং কোনও ক্ষেত্রেই সংকলক দ্বারা সংকেত দেওয়া যেতে পারে। গুরুত্বপূর্ণ বিষয়টি হল আপনি কোন সমস্যার সমাধানের চেষ্টা করছেন সে সম্পর্কে সচেতন হওয়া এবং তারপরে 'কেন?'
ইয়ান গোল্ডবি

@ ইয়ান গোল্ডবি: এর মতো সমস্যাগুলি কেবলমাত্র সংস্থার দ্বারা সংকেত দেওয়া যেতে পারে যদি এতে প্রশ্নে সমস্ত শ্রেণিতে একসাথে অ্যাক্সেস থাকে। কিছু ফ্রেমওয়ার্কে, বেস শ্রেণিতে যে কোনও পরিবর্তন হ'ল সর্বদা উদ্ভূত শ্রেণীর পুনর্নির্মাণের প্রয়োজন হবে, তবে উত্পন্ন ক্লাসগুলি পুনরায় সংকলন না করে বেস শ্রেণীর নতুন সংস্করণগুলি ব্যবহার করার ক্ষমতা (যার জন্য কারও কাছে সোর্স কোড নাও থাকতে পারে) একটি দরকারী বৈশিষ্ট্য is ফ্রেমওয়ার্ক যা এটি সরবরাহ করতে পারে for আরও, সমস্যাগুলি কেবল তাত্ত্বিক নয় tical .NET এর অনেকগুলি ক্লাস এই ধরণের উপর নির্ভর করে যে কোনও রেফারেন্স টাইপ থেকে কোনও টাইপ Objectফিরে আসে ...
সুপারক্যাট

3
@ ইয়ান গোল্ডবি: যথেষ্ট ফর্সা। আমার বক্তব্যটি ছিল যে জাভা এবং .NET এর প্রয়োগকারীরা সাধারণীকৃত এমআইকে সমর্থন না করার সিদ্ধান্ত নেওয়ার ক্ষেত্রে কেবল "অলস" ছিলেন না; সাধারণীকরণযোগ্য এমআইকে সমর্থন করা তাদের কাঠামোকে বিভিন্ন অক্ষরেখাকে ধরে রাখতে বাধা দিতো যার বৈধতা এমআই এর চেয়ে অনেক বেশি ব্যবহারকারীদের পক্ষে কার্যকর more
supercat

21

একাধিক উত্তরাধিকার হ'ল সেই জিনিসগুলির মধ্যে একটি যা প্রায়শই ব্যবহৃত হয় না, এবং এর অপব্যবহার করা যায়, তবে কখনও কখনও এটি প্রয়োজন হয়।

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


আপনি কী ব্যাখ্যা করতে পারেন যে তারা কেন আপনাকে প্রাক এবং পোস্ট শর্ত প্রয়োগ করতে দেয় না?
Yttrill

2
@ Yttrill কারণ ইন্টারফেসের পদ্ধতি প্রয়োগকরণ থাকতে পারে না। কোথায় রাখো assert?
কৌতূহলী

1
@ কুরিয়াসগুয়ে: আপনি একটি উপযুক্ত সিনট্যাক্স সহ এমন একটি ভাষা ব্যবহার করুন যা আপনাকে পূর্ববর্তী এবং পরবর্তী অবস্থার সরাসরি ইন্টারফেসে রাখতে দেয়: কোনও "দৃ "়তা" প্রয়োজন হয় না। ফেলিক্স থেকে উদাহরণ: মজাদার ডিভ (num: int, den: int কখন den! = 0): পূর্বে প্রত্যাশিত ফলাফল == 0 বোঝায় নাম == 0;
Yttrill

@ ইয়িট্রিল ঠিক আছে, তবে কিছু ভাষা, জাভা এর মতো এমআই বা "প্রাক-এবং পোস্ট-শর্তগুলি সরাসরি ইন্টারফেসে সমর্থন করে না"।
কৌতূহলী

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

16

আসুন ধরা যাক আপনার A এবং B অবজেক্টস রয়েছে যা উভয় সি দ্বারা উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছে A এবং B উভয়ই foo () প্রয়োগ করে এবং সি তা করে না। আমি C.foo () কল করি। কোন প্রয়োগটি বেছে নেওয়া হয়? অন্যান্য সমস্যা আছে তবে এই ধরণের জিনিসটি একটি বড় বিষয়।


1
তবে এটি সত্যিই একটি দৃ a় উদাহরণ নয়। যদি A এবং B উভয়টিরই কোনও কার্য থাকে তবে সম্ভবত এটি সম্ভবত সি এর নিজস্ব বাস্তবায়নও প্রয়োজন। অন্যথায় এটি তার নিজের ফু () ফাংশনে এখনও এ :: ফু () কল করতে পারে।
পিটার কাহ্নে 22:25

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

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

2
@ তলোচ - সি যদি অস্পষ্টতার সমাধান না করে তবে সংকলক এই ত্রুটিটি সনাক্ত করতে এবং একটি সংকলন-সময় ত্রুটি ফিরিয়ে দিতে পারে।
ইমন নারবোনে

@ ইয়ারমন - পলিমারফিজমের কারণে, foo () যদি ভার্চুয়াল হয় তবে সংকলকটি সংকলন-সময়ে এও জানতে পারে না যে এটি একটি সমস্যা হতে চলেছে।
tloach

5

একাধিক উত্তরাধিকারের প্রধান সমস্যাটি সুন্দরভাবে উদাহরণের সাথে সংক্ষেপে সংক্ষেপে উল্লেখ করা হয়েছে। একই ফাংশন বা ফিল্ড বাস্তবায়িত করে এমন একাধিক বেস শ্রেণীর উত্তরাধিকার সূত্রে যখন সংকলকটি উত্তরাধিকার সূত্রে কোন বাস্তবায়ন হয় সে সম্পর্কে সিদ্ধান্ত নিতে হয়।

আপনি যখন একই বেস শ্রেণীর উত্তরাধিকারী একাধিক ক্লাস থেকে উত্তরাধিকারী হন তখন এটি আরও খারাপ হয়। (হীরকের উত্তরাধিকার, যদি আপনি উত্তরাধিকার গাছ আঁকেন তবে আপনি হীরার আকার পাবেন)

এই সমস্যাগুলি কোনও সংকলককে কাটিয়ে উঠতে আসলেই সমস্যাযুক্ত নয়। তবে সংকলকটি এখানে যে পছন্দটি করতে হবে তা বরং স্বেচ্ছাসেবী, এই মেক কোডটি স্বল্পতর স্বজ্ঞাত।

আমি দেখতে পেয়েছি যে ভাল ওও ডিজাইন করার সময় আমার কখনও কখনও একাধিক উত্তরাধিকারের প্রয়োজন হয় না। যে ক্ষেত্রে আমার এটির প্রয়োজন হয় আমি সাধারণত খুঁজে পাই যে কার্যকারিতা পুনরায় ব্যবহার করতে আমি উত্তরাধিকার ব্যবহার করছি যখন উত্তরাধিকার কেবল "ইস-এ" সম্পর্কের জন্য উপযুক্ত।

মিক্সিনের মতো অন্যান্য কৌশল রয়েছে যা একই সমস্যাগুলি সমাধান করে এবং একাধিক উত্তরাধিকারের মতো সমস্যাগুলি নেই।


4
সংকলিতকে একটি স্বেচ্ছাসেবী পছন্দ করার প্রয়োজন নেই - এটি কেবল ত্রুটি থেকে বেরিয়ে আসতে পারে। সি # তে কি ধরণের ([..bool..]? "test": 1)?
ইমন নের্বোন

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

5

আমি মনে করি না যে হীরা সমস্যাটি একটি সমস্যা, আমি সেই পরিশীলনটিকে বিবেচনা করব, অন্য কিছুই নয়।

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

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

public sealed class CustomerEditView : Form, MVCView<Customer>

একাধিক উত্তরাধিকার না থাকা নিয়েই আমার এই প্রধান সমস্যা। আপনি ইন্টারফেসের সাথে অনুরূপ কিছু করতে পারেন, তবে আমি যা "এস *** কোড" বলি, এটি এই বেদনাদায়ক পুনরাবৃত্তিক সি *** উদাহরণস্বরূপ, আপনার প্রতিটি ক্লাসে একটি ডেটা প্রসঙ্গ পেতে লিখতে হবে।

আমার মতে, কোনও আধুনিক ভাষায় কোডের পুনরাবৃত্তি করার জন্য একেবারেই প্রয়োজন নেই, সামান্যতমও হওয়া উচিত নয়।


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

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

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

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

3

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


হ্যাঁ,
অতীতকাল

2

একাধিক উত্তরাধিকার নিজেই কোন ভুল নেই। সমস্যাটি হ'ল এমন এক ভাষাতে একাধিক উত্তরাধিকার যুক্ত করা যা শুরু থেকেই একাধিক উত্তরাধিকারের সাথে ডিজাইন করা হয়নি।

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

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

আমি মনে করি যে একাধিক উত্তরাধিকারকে সমর্থন করা বা না করা আরও পছন্দের বিষয়, অগ্রাধিকারের বিষয়। আরও জটিল বৈশিষ্ট্যটি সঠিকভাবে প্রয়োগ এবং পরিচালিত হতে আরও সময় নেয় এবং এটি আরও বিতর্কিত হতে পারে। সি ++ প্রয়োগটি সি # এবং জাভাতে একাধিক উত্তরাধিকার বাস্তবায়ন না করার কারণ হতে পারে ...


1
এমআই এর জন্য সি ++ সমর্থন " খুব দক্ষ এবং উত্পাদনশীল " নয়?
কৌতূহলী

1
আসলে এটি এই অর্থে কিছুটা ভাঙা যা এটি সি ++ এর অন্যান্য বৈশিষ্ট্যের সাথে খাপ খায় না। উত্তরাধিকারের সাথে অ্যাসাইনমেন্ট সঠিকভাবে কাজ করে না, একাধিক উত্তরাধিকারটি ছেড়ে দিন (সত্যই খারাপ নিয়মগুলি দেখুন। হীরা সঠিকভাবে তৈরি করা এত শক্ত যে স্ট্যান্ডার্ডস কমিটি এটিকে সঠিকভাবে না করে বরং সহজ এবং দক্ষ রাখতে ব্যতিক্রম শ্রেণিবিন্যাসকে স্ক্রু করেছে। একটি পুরানো সংকলকটিতে আমি পরীক্ষিত সময়ে আমি ব্যবহার করেছি এবং কয়েকটি এমআই মিশ্রণ এবং মৌলিক ব্যতিক্রমগুলির প্রয়োগগুলি কোডের একটি মেগাবাইটের জন্য ব্যয় করেছিল এবং সংকলন করতে 10 মিনিট সময় নিয়েছিল .. কেবল সংজ্ঞাগুলি।
Yttrill

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

1
এমআই-এর এই মডেলটি দক্ষতার সাথে বাস্তবায়নের জন্য আইফেল সংকলকগণকে একটি বৈশ্বিক প্রোগ্রাম বিশ্লেষণ করতে হবে। পলিমারফিক পদ্ধতিতে কলগুলির জন্য তারা বর্ণিত থানস বা স্পার্স ম্যাট্রিক্সটি এখানে বর্ণিত হিসাবে ব্যবহার করেন । এটি সি ++ এর পৃথক সংকলন এবং সি # এর এবং জাভার ক্লাস লোডিং বৈশিষ্ট্যের সাথে ভালভাবে মেশে না।
cyco130

2

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

সিওএম মডেল যা পূর্ববর্তী .NET এই সাধারণ পদ্ধতির ব্যবহার করার চেষ্টা করেছিল, কিন্তু এর সত্যিকার অর্থে উত্তরাধিকার ছিল না - পরিবর্তে, প্রতিটি শ্রেণীর সংজ্ঞা কার্যকরভাবে একটি শ্রেণি এবং একই নামের ইন্টারফেস উভয়ই সংজ্ঞায়িত করে যা এর সমস্ত জনসাধারণকে ধারণ করে। উদাহরণগুলি শ্রেণীর ধরণের ছিল, যখন উল্লেখগুলি ইন্টারফেস ধরণের ছিল। অন্যটি থেকে প্রাপ্ত ক্লাসকে অন্য শ্রেণীর ইন্টারফেস বাস্তবায়ন হিসাবে শ্রেণীর ঘোষণার সমতুল্য বলে ঘোষণা করা হয়েছিল এবং নতুন শ্রেণীর প্রয়োজন ছিল যেগুলি থেকে প্রাপ্ত সমস্ত শ্রেণীর সদস্যদের পুনরায় প্রয়োগ করা উচিত। যদি Y এবং Z এক্স থেকে উদ্ভূত হয়, এবং তারপরে Y এবং Z থেকে উদ্ভূত হয়, তবে Y এবং Z X এর সদস্যদের আলাদাভাবে প্রয়োগ করে কিনা তা বিবেচ্য হবে না, কারণ Z তাদের বাস্তবায়ন ব্যবহার করতে সক্ষম হবে না - এটির সংজ্ঞা দিতে হবে নিজের। ডাব্লু ওয়াই এবং / অথবা জেড এর উদাহরণগুলি encapsulate করতে পারে,

জাভা এবং .NET এর অসুবিধাটি হ'ল কোডটি সদস্যদের উত্তরাধিকারী হওয়ার মঞ্জুরিপ্রাপ্ত এবং তাদের প্রবেশাধিকার পিতামাতার সদস্যদের স্পষ্টভাবে উল্লেখ করুন । ধরুন যে কারও সাথে ডাব্লুজেডের উপরের মত ক্লাস রয়েছে:

class X { public virtual void Foo() { Console.WriteLine("XFoo"); }
class Y : X {};
class Z : X {};
class W : Y, Z  // Not actually permitted in C#
{
  public static void Test()
  {
    var it = new W();
    it.Foo();
  }
}

দেখে মনে হচ্ছে W.Test()ডাব্লু এর একটি উদাহরণ তৈরি করা উচিত যা Fooসংজ্ঞায়িত ভার্চুয়াল পদ্ধতির প্রয়োগের কল করতে পারে X। ধরুন, তবে, ওয়াই এবং জেড আসলে পৃথক-সংকলিত মডিউলে ছিলেন এবং এক্স এবং ডব্লিউ সংকলনের সময় এগুলি উপরোক্ত হিসাবে সংজ্ঞায়িত হলেও, পরে এগুলি পরিবর্তন ও পুনরায় সংযুক্ত করা হয়েছিল:

class Y : X { public override void Foo() { Console.WriteLine("YFoo"); }
class Z : X { public override void Foo() { Console.WriteLine("ZFoo"); }

এখন ডাকার প্রভাব কী হওয়া উচিত W.Test()? বিতরণ করার আগে যদি প্রোগ্রামটি স্থিতিশীলভাবে সংযুক্ত করতে হয়, তবে স্থির লিঙ্ক পর্যায়ে এটি বুঝতে সক্ষম হতে পারে যে ওয়াই এবং জেড পরিবর্তনের আগে প্রোগ্রামটির কোনও অস্পষ্টতা ছিল না, ওয়াই এবং জেডের পরিবর্তনগুলি বিষয়টিকে অস্পষ্ট করেছে এবং লিঙ্কারটি অস্বীকার করতে পারে এই ধরনের অস্পষ্টতার সমাধান না হওয়া অবধি প্রোগ্রামটি তৈরি করুন। অন্যদিকে, এটি সম্ভবত সম্ভব যে ডাব্লু এবং ওয়াই এবং জেড এর নতুন সংস্করণ উভয়ই সেই ব্যক্তি যিনি কেবল প্রোগ্রামটি চালাতে চান এবং এর কোনওটির জন্য কোনও সোর্স কোড নেই। যখন W.Test()রান, এটি আর পরিষ্কার হবে না কিW.Test() করা উচিত, তবে যতক্ষণ না ব্যবহারকারী ডাব্লু ওয়াই এবং জেড এর নতুন সংস্করণ দিয়ে চালানোর চেষ্টা করেন ততক্ষণ পর্যন্ত সিস্টেমের কোনও অংশই সমস্যা ছিল বুঝতে পারে এমন কোনও উপায় থাকবে না (যদি না ডাব্লু ওয়াই এবং জেড পরিবর্তনের আগেও অবৈধ হিসাবে বিবেচিত হত) ।


2

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

অন্যদিকে, ভার্চুয়াল উত্তরাধিকারের সাথে এটি খুব সহজেই নিয়ন্ত্রণের বাইরে চলে যায় (এবং তারপরেই গোলযোগ হয়)। উদাহরণ হিসাবে একটি "হৃদয়" চিত্র হিসাবে বিবেচনা করুন:

  A       A
 / \     / \
B   C   D   E
 \ /     \ /
  F       G
    \   /
      H

C ++ এটা সম্পূর্ণরূপে অসম্ভব: যত তাড়াতাড়ি Fএবং Gএকটি একক বর্গ মধ্যে মিশে গিয়ে তৈরি করা হয়, তাদের Aগুলি খুব মার্জ করা হয়েছে, কাল। তার মানে আপনি বিবেচনা না পারে বেস ক্লাস সি অস্বচ্ছ ++, (এই উদাহরণে আপনি গঠন করা আছে Aমধ্যে Hযাতে আপনি জানতে হবে এটি অনুক্রমের উপস্থিত কোথাও)। অন্য ভাষায় এটি কার্যকর হতে পারে; উদাহরণস্বরূপ, Fএবং Gস্পষ্টভাবে এটিকে "অভ্যন্তরীণ" হিসাবে ঘোষণা করতে পারে ফলে ফলস্বরূপ মার্জ হওয়া এবং কার্যকরভাবে নিজেকে শক্ত করে তোলা নিষেধ করে।

আরেকটি আকর্ষণীয় উদাহরণ ( না সি ++ - নির্দিষ্ট):

  A
 / \
B   B
|   |
C   D
 \ /
  E

এখানে, কেবল Bভার্চুয়াল উত্তরাধিকার ব্যবহার করা হয়। সুতরাং Eদুটি Bগুলি একই ভাগ করে থাকে A। এই ভাবে, আপনি একটি পেতে পারেন A*পয়েন্টার যে পয়েন্ট E, কিন্তু আপনি না এটি একটি কাস্ট করতে পারবেন B*, যদিও বস্তুর পয়েন্টার হয় আসলে B যেমন ঢালাই দ্ব্যর্থক, এবং এই অস্পষ্টতা (কম্পাইল সময়ে সনাক্ত করা যাবে না যদি না কম্পাইলার দেখেন পুরো প্রোগ্রাম)। পরীক্ষার কোডটি এখানে:

struct A { virtual ~A() {} /* so that the class is polymorphic */ };
struct B: virtual A {};
struct C: B {};
struct D: B {};
struct E: C, D {};

int main() {
        E data;
        E *e = &data;
        A *a = dynamic_cast<A *>(e); // works, A is unambiguous
//      B *b = dynamic_cast<B *>(e); // doesn't compile
        B *b = dynamic_cast<B *>(a); // NULL: B is ambiguous
        std::cout << "E: " << e << std::endl;
        std::cout << "A: " << a << std::endl;
        std::cout << "B: " << b << std::endl;
// the next casts work
        std::cout << "A::C::B: " << dynamic_cast<B *>(dynamic_cast<C *>(e)) << std::endl;
        std::cout << "A::D::B: " << dynamic_cast<B *>(dynamic_cast<D *>(e)) << std::endl;
        std::cout << "A=>C=>B: " << dynamic_cast<B *>(dynamic_cast<C *>(a)) << std::endl;
        std::cout << "A=>D=>B: " << dynamic_cast<B *>(dynamic_cast<D *>(a)) << std::endl;
        return 0;
}

তদুপরি, বাস্তবায়ন খুব জটিল হতে পারে (ভাষার উপর নির্ভর করে; বেঞ্জিসমথের উত্তর দেখুন)।


এটিই এমআইয়ের আসল সমস্যা। প্রোগ্রামারদের এক শ্রেণির মধ্যে বিভিন্ন রেজোলিউশনের প্রয়োজন হতে পারে। একটি ভাষা-বিস্তৃত সমাধান যা সম্ভব তা সীমাবদ্ধ করে এবং প্রোগ্রামারগুলিকে প্রোগ্রামটি সঠিকভাবে কাজ করতে পেতে ক্লডজ তৈরি করতে বাধ্য করেছিল।
shawnhcorey
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.