"চাইল্ড x = নতুন চাইল্ড ();" এর পরিবর্তে "প্যারেন্ট এক্স = নতুন চাইল্ড ();" কি "খারাপ অভ্যাসটি যদি আমরা পরে ব্যবহার করতে পারি?


32

উদাহরণস্বরূপ, আমি এমন কিছু কোড দেখেছি যা এই জাতীয় খণ্ড তৈরি করে:

Fragment myFragment=new MyFragment();

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

MyFragment myFragment=new MyFragment();

যা আরও নির্দিষ্ট, এটি কি সত্য?

বা প্রশ্নের সাধারণীকরণে, এটি ব্যবহার করা কি খারাপ অভ্যাস:

Parent x=new Child();

পরিবর্তে

Child x=new Child();

আমরা যদি পূর্ববর্তীটিকে সংকলন ত্রুটি না করে পরেরটিকে পরিবর্তন করতে পারি?


6
আমরা যদি পরবর্তীটি করি তবে আর বিমূর্তকরণ / জেনারালাইজেশনের কোনও অর্থ নেই। অবশ্যই ব্যতিক্রম আছে ...
ওয়ালফ্র্যাট

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

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

4
অভিভাবক / শিশু ব্যবহার করবেন না। ইন্টারফেস / ক্লাস (জাভা জন্য) ব্যবহার করুন।
থরবজর্ন রাভন অ্যান্ডারসন

4
গুগল কেন "ইন্টারফেসে প্রোগ্রামিং" এটি কেন ব্যবহার Parent x = new Child()করা ভাল ধারণা সম্পর্কে একগুচ্ছ ব্যাখ্যার জন্য ।
কেভিন কর্মী

উত্তর:


69

এটি প্রসঙ্গের উপর নির্ভর করে, তবে আমি যুক্তি দেব যে আপনি সম্ভবত সবচেয়ে বিমূর্তর প্রকারের ঘোষণা করা উচিত । এইভাবে আপনার কোডটি যথাসম্ভব সাধারণ হবে এবং অপ্রাসঙ্গিক বিবরণের উপর নির্ভর করবে না।

একটি উদাহরণ একটি LinkedListএবং ArrayListযা উভয় থেকে অবতরণ করা হবে List। কোডটি যদি কোনও ধরণের তালিকার সাথে সমানভাবে কাজ করে তবে স্বেচ্ছাচারিতায় এটিকে সাবক্লাসগুলির মধ্যে একটিতে সীমাবদ্ধ করার কোনও কারণ নেই।


24
যথাযথভাবে। উদাহরণ যুক্ত করার জন্য, চিন্তা করুন List list = new ArrayList(), তালিকাটি ব্যবহার করে কোডটি কী ধরণের তালিকা তা বিবেচনা করে না, কেবলমাত্র তালিকা ইন্টারফেসের চুক্তি পূরণ করে। ভবিষ্যতে, আমরা সহজেই একটি ভিন্ন তালিকা প্রয়োগে পরিবর্তন করতে পারি এবং অন্তর্নিহিত কোডের কোনও পরিবর্তন বা আপডেট করার দরকার নেই।
পারে_ফ্যাক্টর

19
উত্তম উত্তর তবে প্রসারিত হওয়া উচিত যে বেশিরভাগ বিমূর্ত প্রকারের সম্ভাব্য অর্থ হ'ল সুযোগের কোডটি কিছু শিশু নির্দিষ্ট ক্রিয়াকলাপ সম্পাদন করার জন্য সন্তানের কাছে ফেরত দেওয়া উচিত নয়।
মাইকে

10
@ মাইক: আমি আশা করি এটি না বলে চলে যায়, অন্যথায় সমস্ত ভেরিয়েবল, পরামিতি এবং ক্ষেত্র হিসাবে ঘোষণা করা হবে Object!
জ্যাকবিবি

3
@ জ্যাক্কসবি: যেহেতু এই প্রশ্নোত্তরটি এত বেশি মনোযোগ পেয়েছে আমি ভাবছিলাম যে স্পষ্টভাবে প্রকাশ করা সমস্ত বিভিন্ন দক্ষতার স্তরের লোকদের জন্য কার্যকর হবে।
মাইকে

1
এটি প্রসঙ্গে নির্ভর করে কোনও উত্তর নয়।
বিল্লাল বেগেরাদজ

11

কিছুটা বিমূর্ত হলেও জ্যাকসবির উত্তর সঠিক। আমাকে আরও কিছু বিষয় আরও স্পষ্টভাবে জোর দেওয়া যাক:

আপনার কোড স্নিপেটে আপনি newকীওয়ার্ডটি স্পষ্টভাবে ব্যবহার করেছেন এবং সম্ভবত আপনি আরও সূচনা পদক্ষেপগুলি চালিয়ে যেতে চান যা সম্ভবত কংক্রিটের ধরণের জন্য সুনির্দিষ্ট: তবে আপনাকে সেই নির্দিষ্ট কংক্রিটের ধরণের সাথে ভেরিয়েবলটি ঘোষণা করতে হবে।

যখন আপনি অন্য কোথাও থেকে, যেমন ঐ আইটেমটির পেতে পরিস্থিতি ভিন্ন IFragment fragment = SomeFactory.GiveMeFragments(...);। এখানে, কারখানার সাধারণত সাধারণত সবচেয়ে বিমূর্ত প্রকারটি ফিরিয়ে দেওয়া উচিত, এবং নিম্নমুখী কোডটি প্রয়োগের বিশদগুলির উপর নির্ভর করে না।


18
"যদিও সামান্য বিমূর্ত"। Badumtish।
রসুয়াভ

1
এটি কি সম্পাদনা হতে পারত না?
beppe9000

6

সম্ভাব্য পারফরম্যান্স পার্থক্য রয়েছে।

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

উদাহরণ: ToStringএকটি ভার্চুয়াল কল, কিন্তু Stringসিল করা আছে। চালু আছে String, ToStringকোনও অপশন নেই, সুতরাং আপনি যদি objectএটি ভার্চুয়াল কল হিসাবে ঘোষণা করেন , আপনি যদি Stringকোনও সংকলক ঘোষণা করেন যে কোনও বংশোদ্ভূত শ্রেণি পদ্ধতিটি ওভাররাইড করেছে না কারণ শ্রেণিটি সিল করা আছে, তাই এটি কোনও অপশন নেই। একই বিবেচনার ক্ষেত্রে প্রযোজ্য ArrayListবনাম LinkedList

সুতরাং, যদি আপনি অবজেক্টের কংক্রিটের ধরণটি জানেন, (এবং এটি গোপন করার কোনও encapsulation কারণ নেই), আপনার সেই ধরণের হিসাবে ঘোষণা করা উচিত। যেহেতু আপনি সবেমাত্র অবজেক্টটি তৈরি করেছেন তাই আপনি কংক্রিটের ধরণটি জানেন।


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

এবং সংকলকটি জানে যে "নতুন চাইল্ড ()" কোনও পিতামাতার কাছে নির্ধারিত হয়েও একটি শিশুকে ফিরিয়ে দেয় এবং যতক্ষণ না এটি জানে ততক্ষণ এটি সেই জ্ঞানটি ব্যবহার করতে পারে এবং চাইল্ড () কোডটি কল করতে পারে।
gnasher729

+1 টি। আমার উত্তরে আপনার উদাহরণটিও চুরি করেছে। = পি
নাট

1
নোট করুন যে এখানে পারফরম্যান্স অপটিমাইজেশন রয়েছে যা পুরো জিনিসটিকে মোটা করে তোলে। উদাহরণস্বরূপ হটস্পট লক্ষ্য করবে যে কোনও ফাংশনে পাস করা একটি প্যারামিটার সর্বদা একটি নির্দিষ্ট শ্রেণীর থাকে এবং সে অনুযায়ী অনুকূলিত হয়। যদি এই অনুমানটি কখনই মিথ্যা হয়ে যায় তবে পদ্ধতিটি হ্রাস করা হবে। কিন্তু এটি দৃ strongly়ভাবে সংকলক / রানটাইম পরিবেশের উপর নির্ভর করে। গতবার আমি সিএলআর চেক করেছিলাম যে পি থেকে Parent p = new Child()সবসময়ই একটি শিশু তা
অনুধাবনের

4

মূল পার্থক্য হ'ল প্রয়োজনীয় অ্যাক্সেসের স্তর। এবং বিমূর্ততা সম্পর্কে প্রতিটি ভাল উত্তর প্রাণীদের জড়িত, বা তাই আমাকে বলা হয়।

আমাদের ধরুন আপনার কয়েকটি প্রাণী আছে - Cat Birdএবং Dog। এখন, এই পশুদের কয়েকটি সাধারণ আচরণে আছে - move(), eat()এবং speak()। তারা সকলেই আলাদাভাবে খায় এবং আলাদাভাবে কথা বলে, তবে আমার খাওয়ার বা কথা বলার জন্য যদি আমার প্রাণীর প্রয়োজন হয় তবে তারা কীভাবে এটি করে তা আমি সত্যিই চিন্তা করি না।

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

সুতরাং এমন একটি কোডের জন্য যাতে একটি অনুপ্রবেশকারীকে আমার সত্যিই করা দরকার Dog fido = getDog(); fido.barkMenancingly();

তবে বেশিরভাগ সময়, আমি আনন্দের সাথে যে কোনও প্রাণীর কৌতুক করতে পারে যেখানে তারা ওয়্যারফ, মায়ো বা টুইট করার জন্য টুইট করে for Animal pet = getAnimal(); pet.speak();

সুতরাং আরও কংক্রিট হতে হবে, অ্যারেলিস্টের কিছু পদ্ধতি রয়েছে যা Listনা। উল্লেখযোগ্য trimToSize(),। এখন, 99% ক্ষেত্রে, আমরা এটি সম্পর্কে চিন্তা করি না। Listপ্রায় না বড় যথেষ্ট আমাদের দেখাশোনা করার জন্য। কিন্তু সময় আছে যখন এটি। তাই মাঝে মাঝে, আমাদের অবশ্যই এটির ব্যাকিং অ্যারে আরও ছোট করে ArrayListকার্যকর করার জন্য অনুরোধ trimToSize()করতে হবে।

নোট করুন যে এটি নির্মাণে তৈরি করতে হবে না - এটি সম্পূর্ণরূপে নিশ্চিত হলে এটি একটি রিটার্ন পদ্ধতি বা এমনকি একটি কাস্টের মাধ্যমে করা যেতে পারে।


কেন এটি একটি ডাউনভোট পেতে পারে তা নিয়ে বিভ্রান্ত। এটি ব্যক্তিগতভাবে ব্যক্তিগতভাবে মনে হয়। প্রোগ্রামেবল গার্ড কুকুরের ধারণা বাদে ...
কর্সিকা

কেন আমাকে উত্তরের উত্তর পেতে পাতাগুলি পড়তে হয়েছিল? রেটিং স্তন্যপান।
বাসিলিভস

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

2

সাধারণভাবে বলতে গেলে, আপনার ব্যবহার করা উচিত

var x = new Child(); // C#

অথবা

auto x = new Child(); // C++

স্থানীয় ভেরিয়েবলের ক্ষেত্রে যদি না ভেরিয়েবলের সাথে আরম্ভ করা হয় তার মতো আলাদা ধরণের জন্য উপযুক্ত কারণ থাকে।

(এখানে আমি এই বিষয়টি উপেক্ষা করছি যে সি ++ কোডটি সম্ভবত স্মার্ট পয়েন্টার ব্যবহার করা উচিত There এমন একাধিক লাইন নেই এবং ছাড়াও আমি আসলে জানতে পারি না))

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


1
: C ++, ভেরিয়েবল বেশিরভাগই নতুন শব্দ ছাড়া নির্মিত stackoverflow.com/questions/6500313/...
মারিয়ান Spanik

1
প্রশ্নটি সি # / সি ++ সম্পর্কে নয় তবে কোনও ভাষায় সাধারণ অবজেক্ট ভিত্তিক সমস্যা সম্পর্কে যা অন্তত কিছুটা স্থির টাইপিংয়ের (যেমন, রুবির মতো কিছু জিজ্ঞাসা করা অযৌক্তিক হবে)। তদুপরি, এমনকি এই দুটি ভাষায়ও, আপনি যা বলেছিলেন তেমনভাবে আমাদের কেন করা উচিত তার জন্য আমি সত্যিই কোনও ভাল কারণ দেখতে পাচ্ছি না।
AnoE

1

ভাল কারণ এটি বুঝতে সহজ এবং এই কোডটি সংশোধন করা সহজ:

var x = new Child(); 
x.DoSomething();

ভাল কারণ এটি অভিপ্রায়টি যোগাযোগ করে:

Parent x = new Child(); 
x.DoSomething(); 

ঠিক আছে, কারণ এটি সাধারণ এবং বোঝা সহজ:

Child x = new Child(); 
x.DoSomething(); 

একটি বিকল্প যা সত্যই খারাপ তা হ'ল Parentযদি Childকোনও পদ্ধতি থাকে তবে তা ব্যবহার করা DoSomething()। এটি খারাপ কারণ এটি উদ্দেশ্যকে ভুলভাবে যোগাযোগ করে:

Parent x = new Child(); 
(x as Child).DoSomething(); // DON'T DO THIS! IF YOU WANT x AS CHILD, STORE x AS CHILD

এখন আসুন যে প্রশ্নটি সম্পর্কে বিশেষভাবে জিজ্ঞাসা করা হয়েছে সেটির বিষয়ে আরও কিছুটা বিস্তারিতভাবে বর্ণনা করা যাক:

Parent x = new Child(); 
x.DoSomething(); 

দ্বিতীয়ার্ধে একটি ফাংশন কল করে এটি আলাদাভাবে ফর্ম্যাট করা যাক:

WhichType x = new Child(); 
FunctionCall(x);

void FunctionCall(WhichType x)
    x.DoSomething(); 

এটি সংক্ষিপ্ত করা যেতে পারে:

FunctionCall(new Child());

void FunctionCall(WhichType x)
    x.DoSomething();

এখানে, আমি ধরে নিলাম এটি ব্যাপকভাবে গৃহীত যা WhichTypeসর্বাধিক মৌলিক / বিমূর্ত প্রকার হওয়া উচিত যা ফাংশনটি কাজ করতে দেয় (যদি না পারফরম্যান্সের উদ্বেগ থাকে)। এক্ষেত্রে যথাযথ প্রকারটি হ'ল Parent, বা কিছু Parentথেকে প্রাপ্ত।

এই যুক্তির লাইনটি ব্যাখ্যা করে যে প্রকারটি ব্যবহার করা কেন Parentএকটি ভাল পছন্দ, তবে এটি অন্যান্য পছন্দগুলি খারাপ (এটি নয়) আবহাওয়াতে যায় না।


1

tl; dr - স্থানীয় ব্যাপ্তিতেChildওভার ব্যবহারParentকরা ভাল। এটি কেবল পাঠযোগ্যতার সাথেই সহায়তা করে না, তবে এটিও নিশ্চিত করা দরকার যে ওভারলোডেড পদ্ধতি রেজোলিউশনটি সঠিকভাবে কাজ করে এবং দক্ষ সংকলন সক্ষম করতে সহায়তা করে।


স্থানীয় সুযোগে,

Parent obj = new Child();  // Works
Child  obj = new Child();  // Better
var    obj = new Child();  // Best

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

সম্পূর্ণ ধরণের তথ্য ধরে রাখার চারটি প্রধান সুবিধা রয়েছে:

  1. সংকলক আরও তথ্য সরবরাহ করে।
  2. পাঠককে আরও তথ্য সরবরাহ করে।
  3. ক্লিনার, আরও মানক কোড।
  4. প্রোগ্রামটির যুক্তিটিকে আরও পরিবর্তনযোগ্য করে তোলে।

সুবিধা 1: সংকলক আরও তথ্য

আপাত প্রকারটি ওভারলোডেড পদ্ধতির রেজোলিউশনে এবং অনুকূলিতকরণে ব্যবহৃত হয়।

উদাহরণ: ওভারলোডেড পদ্ধতির রেজোলিউশন

main()
{
    Parent parent = new Child();
    foo(parent);

    Child  child  = new Child();
    foo(child);
}
foo(Parent arg) { /* ... */ }  // More general
foo(Child  arg) { /* ... */ }  // Case-specific optimizations

উপরের উদাহরণে, উভয় foo()কলগুলি কাজ করে তবে একটি ক্ষেত্রে আমরা আরও ভাল লোড পদ্ধতির রেজোলিউশন পাই।

উদাহরণ: সংকলক অপ্টিমাইজেশন

main()
{
    Parent parent = new Child();
    var x = parent.Foo();

    Child  child  = new Child();
    var y = child .Foo();
}
class Parent
{
    virtual         int Foo() { return 1; }
}
class Child : Parent
{
    sealed override int Foo() { return 2; }
}

উপরের উদাহরণে, উভয় .Foo()কলই শেষ পর্যন্ত একই overrideপদ্ধতিতে কল করে 2। কেবলমাত্র, প্রথম ক্ষেত্রে, সঠিক পদ্ধতিটি সন্ধান করার জন্য একটি ভার্চুয়াল পদ্ধতি অনুসন্ধান রয়েছে; এই ভার্চুয়াল পদ্ধতিটি অনুসন্ধানের পদ্ধতিটি দ্বিতীয় ক্ষেত্রে প্রয়োজন নেই sealed

@ বেনকে ক্রেডিট করুন যিনি তার উত্তরে একই উদাহরণ দিয়েছেন

সুবিধা 2: পাঠকের আরও তথ্য

সঠিক ধরণটি জানার অর্থ Child, যিনি কোডটি পড়ছেন তার আরও বেশি তথ্য সরবরাহ করে, প্রোগ্রামটি কী করছে তা আরও সহজ করে তোলে।

অবশ্যই, সম্ভবত এটি উভয় থেকেই আসল কোডের সাথে কিছু যায় আসে না parent.Foo();child.Foo(); গুরুত্ব এবং বোঝায়, তবে প্রথমবারের মতো কোডটি দেখার জন্য কারও কাছে আরও তথ্যের সাদামাটা সহায়ক।

অতিরিক্তভাবে, আপনার বিকাশের পরিবেশের উপর নির্ভর করে আইডিই প্রায় আরও সহায়ক সরঞ্জামদণ্ড এবং মেটাডেটা সরবরাহ করতে সক্ষম হতে পারে Child চেয়েParent

সুবিধা 3: ক্লিনার, আরও মানক কোড

আমি ইদানীং ব্যবহার করা সি-কোড উদাহরণগুলির বেশিরভাগই varমূলত শর্টহ্যান্ড Child

Parent obj = new Child();  // Sub-optimal
Child  obj = new Child();  // Optimal, but anti-pattern syntax
var    obj = new Child();  // Optimal, clean, patterned syntax "everyone" uses now

অ- varঘোষণাপত্রের বিবৃতি দেখলে তা বন্ধ হয়ে যায়; যদি এর কোনও পরিস্থিতিগত কারণ থাকে, দুর্দান্ত, তবে অন্যথায় এটি অ্যান্টি-প্যাটার্ন দেখায়।

// Clean:
var foo1 = new Person();
var foo2 = new Job();
var foo3 = new Residence();

// Staggered:
Person foo1 = new Person();
Job foo2 = new Job();
Residence foo3 = new Residence();   

সুবিধা 4: প্রোটোটাইপিংয়ের জন্য আরও পরিবর্তনীয় প্রোগ্রামের যুক্তি

প্রথম তিনটি সুবিধা ছিল বড়গুলি; এটি একের থেকে অনেক বেশি পরিস্থিতিগত।

তবুও, অন্যদের মতো কোড ব্যবহার করা লোকেরা এক্সেল ব্যবহার করে, আমরা ক্রমাগত আমাদের কোড পরিবর্তন করি। হয়তো আমরা একটি পদ্ধতি অনন্য কল করার প্রয়োজন হবে না Childযে এই কোডের সংস্করণ, কিন্তু আমরা repurpose বা পরে কোড rework পারে।

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

সারাংশ

ব্যবহার Parentমেসস আপ ওভারলোডেড পদ্ধতি রেজোলিউশন কিছু সংকলক অনুকূলকরণ বাধা দেয়, পাঠকের কাছ থেকে তথ্য সরিয়ে দেয় এবং কোডটি আরও খারাপ করে তোলে।

ব্যবহার varকরা সত্যিই যাওয়ার উপায়। এটি দ্রুত, পরিষ্কার, প্যাটার্নযুক্ত এবং সংকলক এবং আইডিইকে তাদের কাজটি সঠিকভাবে করতে সহায়তা করে।


গুরুত্বপূর্ণ : এই উত্তরটিকোনও পদ্ধতির স্থানীয় স্কোপেপ্রায়ParentবনামChildParentবনামেরইস্যুটিChildরিটার্নের ধরণ, যুক্তি এবং শ্রেণীর ক্ষেত্রে খুব আলাদা very


2
আমি এটি যুক্ত করব যে Parent list = new Child()খুব বেশি অর্থ হয় না। যে কোডটি সরাসরি কোনও অবজেক্টের কংক্রিট উদাহরণ তৈরি করে (কারখানার মাধ্যমে কারখানা, কারখানার পদ্ধতি ইত্যাদির বিপরীতে) সঠিকভাবে তৈরি হওয়া ধরণের সম্পর্কে সঠিক তথ্য রয়েছে, এটি সদ্য নির্মিত বস্তু ইত্যাদি কনফিগার করার জন্য কংক্রিট ইন্টারফেসের সাথে যোগাযোগের প্রয়োজন হতে পারে might স্থানীয় সুযোগটি যেখানে আপনি নমনীয়তা অর্জন করেন তা নয় । নমনীয়তা অর্জন করা হয় যখন আপনি নতুন শ্রেণীর ক্লায়েন্টকে আরও বিমূর্ত ইন্টারফেস ব্যবহার করে নতুনভাবে তৈরি করা বস্তুটি প্রকাশ করেন (কারখানা এবং কারখানার পদ্ধতিগুলি একটি নিখুঁত উদাহরণ)
ক্রিজিস

"টিএল; ডাঃ পিতামাতার উপরে পিতামাত ব্যবহার করা স্থানীয় ক্ষেত্রে বেশি পছন্দনীয় It এটি কেবল পাঠযোগ্যতার সাথেই সহায়তা করে না," - অগত্যা নয় ... যদি আপনি শিশু নির্দিষ্টকরণের কোনও ব্যবহার না করেন তবে এটি প্রয়োজনের চেয়ে আরও বিশদ যুক্ত করবে। "তবে ওভারলোডেড পদ্ধতির রেজোলিউশন সঠিকভাবে কাজ করে এবং দক্ষ সংকলন সক্ষম করতে সহায়তা করে তাও নিশ্চিত করা জরুরি।" - এটি প্রোগ্রামিং ভাষার উপর অনেক বেশি নির্ভর করে। এখানে প্রচুর সমস্যা রয়েছে যা প্রচুর আছে।
AnoE

1
আপনি যে একটি উৎস আছে না Parent p = new Child(); p.doSomething();এবং Child c = new Child; c.doSomething();বিভিন্ন আচরণ আছে? হতে পারে এটি কোনও ভাষায় এক গলফ, তবে মনে করা হয় যে বিষয়টিটি রেফারেন্স নয়, আচরণটি নিয়ন্ত্রণ করে। এটাই উত্তরাধিকারের সৌন্দর্য! অভিভাবক বাস্তবায়নের চুক্তিটি পূরণ করতে আপনি যতক্ষণ সন্তানের বাস্তবায়নে বিশ্বাস করতে পারেন ততক্ষণ আপনি যেতে ভাল।
কর্সিকা

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

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

0

প্রদত্ত parentType foo = new childType1();, কোডটি প্যারেন্ট-টাইপ পদ্ধতিগুলিতে ব্যবহারের মধ্যে সীমাবদ্ধ থাকবে fooতবে fooযে কোনও বস্তুর প্রকার - parentকেবল উদাহরণস্বরূপ থেকে প্রাপ্ত কোনও পদার্থের রেফারেন্সে সঞ্চয় করতে সক্ষম হবে childType1। নতুন childType1উদাহরণটি যদি কেবলমাত্র কোনও জিনিসই fooরেফারেন্স রাখে, তবে fooএর ধরণের হিসাবে এটির ঘোষণা দেওয়া ভাল childType1। অন্যদিকে, যদি fooঅন্য ধরণের রেফারেন্স রাখা দরকার হয়, এটি হিসাবে ঘোষণা করা parentTypeসম্ভব করে তুলবে।


0

আমি ব্যবহার করার পরামর্শ দিচ্ছি

Child x = new Child();

পরিবর্তে

Parent x = new Child();

পূর্ববর্তী তথ্য হারায় যদিও প্রাক্তন তথ্য না দেয়।

আপনি পূর্বের সাথে যা করতে পারেন তা আপনি পরে করতে পারেন তবে বিপরীতে নয়।


পয়েন্টারটি আরও বিস্তৃত করতে, আসুন আপনার উত্তরাধিকারের একাধিক স্তর রয়েছে।

Base-> DerivedL1->DerivedL2

এবং আপনি new DerivedL2()একটি পরিবর্তনশীল এর ফলাফল আরম্ভ করতে চান । বেস টাইপ ব্যবহার করা আপনাকে ব্যবহারের বিকল্প Baseবা ছেড়ে দেয় DerivedL1

তুমি ব্যবহার করতে পার

Base x = new DerivedL2();

অথবা

DerivedL1 x = new DerivedL2();

একে অপরের চেয়ে পছন্দ করার কোনও যৌক্তিক উপায় আমি দেখতে পাচ্ছি না।

আপনি যদি ব্যবহার

DerivedL2 x = new DerivedL2();

এ নিয়ে তর্ক করার কিছু নেই।


3
আপনার আরও বেশি কিছু করার দরকার না পড়লে কম করতে সক্ষম হওয়াই ভাল জিনিস, না?
পিটার

1
@ পিটার, কম করার ক্ষমতা সীমাবদ্ধ নয়। এটা সর্বদা সম্ভব। যদি আরও করার ক্ষমতা সীমাবদ্ধ থাকে তবে এটি একটি ব্যথার কারণ হতে পারে।
আর সাহু

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

@ মাআর্টিনাস, আমি অবাক হয়েছি বেশিরভাগ ব্যবহারকারীর তথ্য হারাতে পছন্দ করেন। অন্যের মতো স্পষ্টভাবে তথ্য হারাবার সুবিধা আমি দেখছি না।
আর সাহু

আপনি যখন ঘোষণা করেন Base x = new DerivedL2();তখন আপনি সর্বাধিক সীমাবদ্ধ এবং এটি আপনাকে ন্যূনতম চেষ্টা করে অন্য (বৃদ্ধ) শিশুটিকে স্যুইচ করতে দেয় allows তদুপরি, আপনি অবিলম্বে দেখুন যে এটি সম্ভব। +++ আমরা void f(Base)কি এর চেয়ে ভাল এর সাথে একমত void f(DerivedL2)?
মার্টিনাস

0

আমি সর্বদা সর্বাধিক নির্দিষ্ট ধরণের হিসাবে ভেরিয়েবলগুলি ফিরিয়ে আনার বা সংরক্ষণ করার পরামর্শ দিচ্ছি, তবে পরামিতিগুলিকে বিস্তৃত প্রকার হিসাবে গ্রহণ করার পরামর্শ দিচ্ছি।

যেমন

<K, V> LinkedHashMap<K, V> keyValuePairsToMap(List<K> keys, List<V> values) {
   //...
}

পরামিতিগুলি List<T>, খুব সাধারণ ধরণের। ArrayList<T>,LinkedList<T> এবং অন্যরা সবাই এই পদ্ধতিতে গৃহীত হতে পারে।

গুরুত্বপূর্ণভাবে, রিটার্ন টাইপ হয় LinkedHashMap<K, V>, না Map<K, V>। যদি কেউ এই পদ্ধতির ফলাফলকে একটিতে নির্ধারণ করতে চায় তবেMap<K, V> তারা এটি করতে পারে। এটি পরিষ্কারভাবে যোগাযোগ করে যে এই ফলাফলটি কেবল একটি মানচিত্রের চেয়ে বেশি নয়, তবে একটি সংজ্ঞায়িত ক্রমযুক্ত মানচিত্র।

মনে করুন এই পদ্ধতিটি ফিরে এসেছে Map<K, V>। যদি কলকারী একটি চায় LinkedHashMap<K, V>, তাদের একটি প্রকারের চেক, কাস্ট এবং ত্রুটি পরিচালনার কাজ করতে হবে যা সত্যই জটিল।


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

@ কর্সিকা হুম আমি সম্মত হলাম এটি একটি আরও ভাল নাম তবে এটি কেবল একটি উদাহরণ। আমি একমত নই যে (সাধারণভাবে) আপনার রিটার্নের প্রসারকে আরও ভাল করা। আপনার কৃত্রিমভাবে কোনও প্রকার সমর্থন ছাড়াই প্রকারের তথ্য সরানো। যদি আপনি কল্পনা করেন যে আপনার ব্যবহারকারীর যথাযথভাবে আপনি যে বিস্তৃত প্রকারগুলি সরবরাহ করেছেন তা ফেরত দিতে হবে, তবে আপনি সেগুলি একটি বিঘ্নিত কাজ করেছেন।
আলেকজান্ডার - মনিকা পুনরায়

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

প্রকৃতপক্ষে, আমি শেষ বাক্য অবধি এই সমস্ত পথেই একমত। আপনি থেকে পরিবর্তিত LinkedHashMapকরা TreeMapযেমন থেকে পরিবর্তন, একটি তুচ্ছ পরিবর্তন নয় ArrayListথেকে LinkedList। এটি অর্থগত গুরুত্ব সহ একটি পরিবর্তন। সেক্ষেত্রে আপনি সংকলকটি একটি ত্রুটি নিক্ষেপ করতে চান , ফেরতের মূল্যের গ্রাহকদের পরিবর্তনটি লক্ষ্য করতে এবং উপযুক্ত পদক্ষেপ নিতে বাধ্য করুন।
আলেকজান্ডার - মনিকা পুনরায়

তবে এটি একটি তুচ্ছ পরিবর্তন হতে পারে যদি আপনার সমস্ত যত্ন করা মানচিত্রের আচরণ হয় (যা, যদি আপনি পারেন তবে আপনার উচিত)) চুক্তিটি যদি "আপনি একটি মূল মানচিত্র পাবেন" এবং অর্ডার কোনও ব্যাপার না (তবে এটি সত্য) সর্বাধিক মানচিত্র) তবে এটি গাছ বা হ্যাশ মানচিত্র কিনা তা বিবেচনা করে না। উদাহরণস্বরূপ, Thread#getAllStackTraces()- রাস্তার নিচে Map<Thread,StackTraceElement[]>একটি HashMapনির্দিষ্ট পরিবর্তে একটি পরিবর্তিত করে তারা এটিকে Mapতারা যে প্রকারের থেকে এটি পরিবর্তন করতে পারে ।
কর্সিকা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.