কেন জাভা বিপরীতে "নতুন" এবং "ভার্চুয়াল + ওভাররাইড" কীওয়ার্ড দিয়ে সি # তৈরি করা হয়েছিল?


61

জাভা সেখানে নেই virtual, new, overrideপদ্ধতি সংজ্ঞা জন্য কীওয়ার্ড। সুতরাং একটি পদ্ধতির কাজ বোঝা সহজ। কারণ যদি ডেরিভডক্লাস বেসক্লাসকে প্রসারিত করে এবং বেসক্লাসের একই নাম এবং একই স্বাক্ষর সহ একটি পদ্ধতি থাকে তবে রান-টাইম পলিমারফিজমে ( ওপথটি পদ্ধতিটি নয় static) ওভাররাইডিং হবে place

BaseClass bcdc = new DerivedClass(); 
bcdc.doSomething() // will invoke DerivedClass's doSomething method.

এখন সি # আসা এত বিভ্রান্তি ও কঠোর কিভাবে বুঝতে থাকতে পারে newবা virtual+deriveবা নতুন + ভার্চুয়াল ওভাররাইড কাজ করে যাচ্ছে।

আমি কেন বুঝতে পারছি না যে আমি কেন পৃথিবীতে আমি DerivedClassএকই নাম এবং একই স্বাক্ষর সহ একটি পদ্ধতি যুক্ত করব BaseClassএবং একটি নতুন আচরণ সংজ্ঞায়িত করব তবে রান-টাইম বহুরূপী সময়ে, BaseClassপদ্ধতিটি আহ্বান করা হবে! (যা ওভাররাইডিং নয় তবে যৌক্তিকভাবে এটি হওয়া উচিত)।

ক্ষেত্রে virtual + overrideযদিও যৌক্তিক বাস্তবায়ন সঠিক, কিন্তু প্রোগ্রামার চিন্তা করতে যা পদ্ধতি তিনি কোডিং করার সময় ওভাররাইড করতে ব্যবহারকারীকে অনুমতি দিতে হবে না। যার কিছুটা প্রো-কন রয়েছে (আসুন এখন সেখানে যাব না)।

সুতরাং কেন সি # তে আন- লজিকাল যুক্তি এবং বিভ্রান্তির জন্য এত জায়গা রয়েছে । তাই আমি যা বাস্তব জগতে প্রেক্ষাপটে যেমন আমার প্রশ্ন reframe পারে আমি ব্যবহারের চিন্তা করা উচিত virtual + overrideপরিবর্তে newএবং ব্যবহারের newপরিবর্তে virtual + override?


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

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

Vehicle vehicle = new Car();
vehicle.accelerate();

এবং পরে আমি নতুন ক্লাস SpaceShipথেকে উদ্ভূত Vehicle। তারপরে আমি সবগুলিকে carএকটি SpaceShipঅবজেক্টে পরিবর্তন করতে চাই আমাকে কেবল কোডের একক লাইন পরিবর্তন করতে হবে

Vehicle vehicle = new SpaceShip();
vehicle.accelerate();

কোডের কোনও বিন্দুতে এটি আমার কোনও যুক্তি ভঙ্গ করবে না।

তবে সি # এর ক্ষেত্রে যদি ক্লাসটি SpaceShipওভাররাইড না করে Vehicle' accelerateএবং ব্যবহার করে newতবে আমার কোডের লজিকটি নষ্ট হয়ে যাবে। এটা কি অসুবিধা নয়?


77
আপনি জাভা যেভাবে করেন তা সবেমাত্র ব্যবহার করেছেন এবং তাদের নিজস্ব শর্তাদি C # কীওয়ার্ড বুঝতে সময় লাগেনি the আমি সি # এর সাথে কাজ করি, তত্ক্ষণাত শর্তাদি বুঝতে পেরেছি এবং জাভা কীভাবে এইভাবে বেআইনী আচরণ করে তা আবিষ্কার করি।
রবার্ট হার্ভে

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

15
"জাভাতে পদ্ধতির সংজ্ঞার জন্য কোনও ভার্চুয়াল, নতুন, ওভাররাইড কীওয়ার্ড নেই” "বাদে রয়েছে @Override
সুইভ


3
@ সিভিক টীকা এবং কীওয়ার্ডগুলি এক জিনিস নয় :)
অনির্বাণ নাগ 'টিনটিনমজ'

উত্তর:


86

যেহেতু আপনি জিজ্ঞাসা করেছেন কেন সি # কেন এটি করেছে, তাই সি # নির্মাতাদের জিজ্ঞাসা করা ভাল। সি # এর প্রধান স্থপতি আন্ডারস হেজলসবার্গ উত্তর দিয়েছেন যে তারা কেন একটি সাক্ষাত্কারে ডিফল্টরূপে (জাভা হিসাবে) ভার্চুয়ালের সাথে না যেতে পছন্দ করেছিল , প্রাসঙ্গিক স্নিপেটগুলি নীচে রয়েছে।

মনে রাখবেন যে জাভাটির অ-ভার্চুয়াল হিসাবে কোনও পদ্ধতি চিহ্নিত করার জন্য চূড়ান্ত কীওয়ার্ড সহ ডিফল্টরূপে ভার্চুয়াল রয়েছে। এখনও দুটি ধারণাগুলি শিখতে হবে, তবে অনেক লোক চূড়ান্ত কীওয়ার্ড সম্পর্কে জানেন না বা সক্রিয়ভাবে ব্যবহার করবেন না। সি # এই সিদ্ধান্তগুলি সচেতনভাবে করার জন্য ভার্চুয়াল এবং নতুন / ওভাররাইড ব্যবহার করতে বাধ্য করে।

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

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

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

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

বিকাশকারীরা শ্রেণীর উত্তরাধিকারের নকশা সম্পর্কে কীভাবে চিন্তাভাবনা করে এবং কীভাবে তাদের সিদ্ধান্তটি নিয়েছিল সে সম্পর্কে সাক্ষাত্কারটিতে আরও আলোচনা রয়েছে।

এখন নীচের প্রশ্নের:

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

এটি তখন ঘটবে যখন কোনও উদ্ভূত শ্রেণি ঘোষণা করতে চায় যে এটি বেস বর্গের চুক্তি মেনে চলে না, তবে একই নামের একটি পদ্ধতি রয়েছে। (যে কেউ সি # এর মধ্যে newএবং তার overrideমধ্যে পার্থক্য জানেন না , তার জন্য এই এমএসডিএন পৃষ্ঠাটি দেখুন )।

একটি খুব বাস্তব পরিস্থিতি হ'ল:

  • আপনি একটি এপিআই তৈরি করেছেন, যার একটি ক্লাস রয়েছে Vehicle
  • আমি আপনার এপিআই ব্যবহার শুরু করেছি এবং উত্পন্ন করেছি Vehicle
  • আপনার Vehicleক্লাসে কোনও পদ্ধতি ছিল না PerformEngineCheck()
  • আমার Carক্লাসে, আমি একটি পদ্ধতি যুক্ত করি PerformEngineCheck()
  • আপনি আপনার API এর একটি নতুন সংস্করণ প্রকাশ করেছেন এবং একটি যুক্ত করেছেন PerformEngineCheck()
  • আমি আমার পদ্ধতির নাম পরিবর্তন করতে পারি না কারণ আমার ক্লায়েন্টরা আমার API এর উপর নির্ভরশীল, এবং এটি তাদের ভেঙে দেবে।
  • সুতরাং যখন আমি আপনার নতুন এপিআইয়ের বিরুদ্ধে পুনরায় রচনা করি তখন সি # আমাকে এই সমস্যাটি সম্পর্কে সতর্ক করে, যেমন

    বেসটি PerformEngineCheck()না থাকলে virtual:

    app2.cs(15,17): warning CS0108: 'Car.PerformEngineCheck()' hides inherited member 'Vehicle.PerformEngineCheck()'.
    Use the new keyword if hiding was intended.
    

    এবং যদি বেসটি PerformEngineCheck()ছিল virtual:

    app2.cs(15,17): warning CS0114: 'Car.PerformEngineCheck()' hides inherited member 'Vehicle.PerformEngineCheck()'.
    To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
    
  • এখন, আমার ক্লাসটি আসলে বেস ক্লাসের চুক্তিটি প্রসারিত করছে কিনা তা স্পষ্ট করেই আমাকে সিদ্ধান্ত নিতে হবে, বা এটি যদি অন্য চুক্তি হয় তবে একই নামে হয়।

  • এটি তৈরির মাধ্যমে new, যদি বেস পদ্ধতির কার্যকারিতা উত্পন্ন পদ্ধতি থেকে আলাদা হয় তবে আমি আমার ক্লায়েন্টদের ভাঙ্গি না। রেফারেন্সযুক্ত যে কোনও কোডই কল Vehicleদেখতে পাবে না Car.PerformEngineCheck(), তবে যে কোডটিতে একটি রেফারেন্স Carছিল সেটিতে আমি যে অফারটি দিয়েছিলাম তা একই কার্যকারিতাটি দেখতে থাকবে PerformEngineCheck()

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

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

অ্যান্ডারস বলেছিলেন, সত্যিকারের বিশ্ব আমাদেরকে এমন বিষয়গুলিতে জোর করে, যা আমরা যদি স্ক্র্যাচ থেকে শুরু করি, আমরা কখনই তাতে প্রবেশ করতে চাই না।

সম্পাদনা: newইন্টারফেসের সামঞ্জস্যতা নিশ্চিত করার জন্য কোথায় ব্যবহার করতে হবে তার একটি উদাহরণ যুক্ত করা হয়েছে।

সম্পাদনা: মন্তব্যগুলি করার সময়, আমি এরিক লিপার্টের (তখন সি # ডিজাইন কমিটির সদস্যদের মধ্যে একজন) অন্যান্য উদাহরণের দৃশ্যের (ব্রায়ান দ্বারা উল্লিখিত) একটি লেখাও পেয়েছিলাম ।


পার্ট 2: আপডেট হওয়া প্রশ্নের ভিত্তিতে

তবে সি # এর ক্ষেত্রে স্পেসশিপ যদি যানবাহন শ্রেণিকে 'ত্বরান্বিত করে নতুন ব্যবহার না করে তবে আমার কোডটির যুক্তিটি ভেঙে যাবে। এটা কি অসুবিধা নয়?

কে সিদ্ধান্ত নেয় যে SpaceShipআসলে ওভাররাইড করছে কিনা Vehicle.accelerate()বা এটি আলাদা কিনা? এটি SpaceShipডেভেলপার হতে হবে । সুতরাং যদি SpaceShipবিকাশকারী সিদ্ধান্ত নেন যে তারা বেস ক্লাসের চুক্তি পালন করছেন না, তবে আপনার কলটি করা Vehicle.accelerate()উচিত নয় SpaceShip.accelerate(), বা করা উচিত? তারা যখন এটিকে চিহ্নিত করবে new। তবে, যদি তারা সিদ্ধান্ত নেয় যে এটি সত্যই চুক্তিটি রাখে, তবে তারা প্রকৃতপক্ষে এটি চিহ্নিত করবে override। উভয় ক্ষেত্রেই, আপনার কোড চুক্তির ভিত্তিতে সঠিক পদ্ধতিটি কল করে সঠিকভাবে আচরণ করবে । আপনার কোডটি কীভাবে সিদ্ধান্ত নিতে পারে যে SpaceShip.accelerate()এটি আসলে ওভাররাইড করছে কিনা Vehicle.accelerate()বা এটি নামের সংঘর্ষ কিনা ? (উপরে আমার উদাহরণ দেখুন)।

যাইহোক, অন্তর্নিহিত উত্তরাধিকার ক্ষেত্রে, এমনকি যদি SpaceShip.accelerate()রক্ষা না চুক্তি এর Vehicle.accelerate(), পদ্ধতি কল এখনও যেতে হবে SpaceShip.accelerate()


12
পারফরম্যান্স পয়েন্ট এখনই সম্পূর্ণ অপ্রচলিত। একটি প্রমাণের জন্য দেখুন আমার বেঞ্চমার্কটি দেখায় যে কোনও চূড়ান্ত নয় তবে কখনও ওভারলোডেড পদ্ধতির মাধ্যমে কোনও ক্ষেত্র অ্যাক্সেস করতে একটি চক্র লাগে না।
মার্টিনাস

7
অবশ্যই, এটি হতে পারে। প্রশ্নটি ছিল যখন সি # যখন এটি করার সিদ্ধান্ত নিয়েছে তখন কেন এটি করা হয়েছিল এবং তাই এই উত্তরটি বৈধ। যদি প্রশ্নটি এখনও বোঝা যায় কিনা, তবে এটি আলাদা আলোচনা, আইএমএইচও।
ওমর ইকবাল

1
আমি সম্পূর্ণরূপে আপনার সাথে একমত।
মার্টিনাস

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

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

94

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


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

21
এরিক লিপার্ট তার পোস্ট, ভার্চুয়াল পদ্ধতি এবং ভঙ্গুর বেস ক্লাসগুলিতে এ সম্পর্কে বিস্তারিত আলোচনা করেছেন ।
ব্রায়ান

12
জাভা finalসংশোধক আছে, তাই সমস্যা কি?
সার্জে বোর্স

13
@ করসিকা "অবজেক্টগুলির এক্সটেনশনের জন্য উন্মুক্ত হওয়া উচিত" - কেন? যদি বেস শ্রেণীর বিকাশকারী কখনও উত্তরাধিকার সম্পর্কে চিন্তা না করে তবে এটি প্রায় গ্যারান্টেড যে কোডটিতে সূক্ষ্ম নির্ভরতা এবং অনুমান রয়েছে যা বাগগুলি বাড়াবে (মনে রাখবেন HashMap?)। হয় উত্তরাধিকারের জন্য ডিজাইন করুন এবং চুক্তিটি পরিষ্কার করুন বা করবেন না এবং নিশ্চিত করুন যে কেউ শ্রেণির উত্তরাধিকারী হতে পারে না। @Overrideবান্দাইদ হিসাবে যুক্ত করা হয়েছিল কারণ ততক্ষণে আচরণটি পরিবর্তন করতে খুব দেরি হয়েছিল, তবে এমনকি মূল জাভা দেবগণ (বিশেষত জোশ ব্লচ) সম্মত হন যে এটি একটি খারাপ সিদ্ধান্ত ছিল।
ভু

9
@ জেভিং "মতামত" একটি মজার শব্দ; লোকেরা এটিকে সত্যের সাথে সংযুক্ত করতে পছন্দ করে যাতে তারা এগুলি উপেক্ষা করতে পারে। তবে যা কিছু তা মূল্যবান তা জোশুয়া ব্লচের "মতামত" (দেখুন: কার্যকর জাভা , আইটেম 17 ), জেমস গোসলিংয়ের "মতামত" ( এই সাক্ষাত্কারটি দেখুন ), এবং ওমর ইকবালের উত্তরে যেমন উল্লেখ করা হয়েছে , এটি এন্ডারস হজলসবার্গের "মতামত "ও রয়েছে। (এবং যদিও তিনি কখনও বনাম বাছাইয়ের বিষয়টি বেছে নেননি, এরিক লিপার্ট স্পষ্টভাবে সম্মত হন যে উত্তরাধিকারটিও বিপজ্জনক)) তবে কাদের কথা বলা হচ্ছে?
ডোভাল

33

যেমন রবার্ট হার্ভি বলেছেন, আপনি যা অভ্যস্ত তা সবই এর মধ্যে। আমি জাভা এর এই নমনীয়তা অভাব অদ্ভুত।

সে বলেছিল, কেন এটি প্রথম স্থানে আছে? একই কারণে C # এর যে জন্য public, internal(এছাড়াও "কিছুই"), protected, protected internal, এবং private, কিন্তু জাভা মাত্র হয়েছে public, protectedকিছুই আর private। এটি আপনি যে কোডিং করছেন তার আচরণের উপরে আরও শর্তাবলী এবং কীওয়ার্ড রাখার ব্যয়ে সূক্ষ্ম শস্য নিয়ন্ত্রণ সরবরাহ করে।

newবনামের ক্ষেত্রে virtual+override, এটি এরকম কিছু হয়:

  • আপনি পদ্ধতি বাস্তবায়ন করতে উপশ্রেণী বাধ্য করতে চান, ব্যবহার abstract, এবং overrideউপশ্রেণী হবে।
  • আপনি যদি কার্যকারিতা সরবরাহ করতে চান তবে সাবক্লাসটিকে এটি প্রতিস্থাপন, ব্যবহার virtualএবং overrideসাবক্লাসে অনুমতি দিন।
  • যদি আপনি কার্যকারিতা সরবরাহ করতে চান যা উপশ্রেণীর কখনই ওভাররাইডের প্রয়োজন হবে না, কিছু ব্যবহার করবেন না।
    • তারপর আপনি একটি বিশেষ ক্ষেত্রে উপশ্রেণী যা থাকে না ভিন্নভাবে আচরণ করতে হবে, ব্যবহার newউপশ্রেণী হবে।
    • যদি আপনি নিশ্চিত করতে চান যে কোনও সাবক্লাস কখনই আচরণটি ওভাররাইড করতে sealedনা পারে তবে বেস ক্লাসে ব্যবহার করুন ।

বাস্তব-বিশ্বের উদাহরণের জন্য: একটি প্রকল্প যা আমি বিভিন্ন উত্স থেকে প্রক্রিয়াকৃত ইকমার্স অর্ডারে কাজ করেছি। এখানে একটি বেস OrderProcessorছিল যার বেশিরভাগ যুক্তি ছিল, প্রতিটি উত্সের শিশু শ্রেণির ওভাররাইডের জন্য নির্দিষ্ট abstract/ virtualপদ্ধতি সহ । এটি ঠিকঠাক কাজ করেছিল, যতক্ষণ না আমরা একটি নতুন উত্স পেয়েছি যার প্রক্রিয়াকরণের অর্ডারগুলির সম্পূর্ণ ভিন্ন পদ্ধতি ছিল, যেমন আমাদের একটি মূল ফাংশন প্রতিস্থাপন করতে হয়েছিল। আমাদের এই মুহুর্তে দুটি পছন্দ ছিল: 1) virtualবেস পদ্ধতিতে যুক্ত করুন, এবং overrideসন্তানের মধ্যে; বা 2) newসন্তানের সাথে যুক্ত করুন।

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

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


7
আমি মনে করি যে ইচ্ছাকৃতভাবে ব্যবহার newএই ভাবে একটি বাগ ঘটতে অপেক্ষা করছে। যদি আমি কোনও পদ্ধতিকে কল করি তবে আমি উদাহরণটি তার বেস বর্গে ফেলে দিলেও, এটি সর্বদা একই কাজ করার প্রত্যাশা করি। তবে newএড পদ্ধতিগুলি এমনভাবে আচরণ করে না।
সোভিক

@ স্পিক - সম্ভাব্য, হ্যাঁ আমাদের বিশেষ দৃশ্যে, এটি কখনই ঘটে না, তবে সে কারণেই আমি সতর্কতা যুক্ত করেছি।
ববসন

এর একটি দুর্দান্ত ব্যবহার newএমভিসি ফ্রেমওয়ার্কের ওয়েবভিউপেজ <টিমোডেল> এ। তবে আমি newকয়েক ঘন্টা জড়িত একটি বাগ দ্বারা নিক্ষেপ করেছি, তাই আমি মনে করি না এটি একটি অযৌক্তিক প্রশ্ন।
পিডিআর

1
@ সিচ্যাম্পাগেন: যে কোনও সরঞ্জাম খারাপভাবে ব্যবহার করা যেতে পারে এবং এটি একটি বিশেষত একটি ধারালো সরঞ্জাম - আপনি নিজেকে সহজে কাটতে পারেন। তবে এটি টুলবক্স থেকে সরঞ্জামটি সরিয়ে এবং আরও প্রতিভাবান এপিআই ডিজাইনারের বিকল্প অপসারণ করার কোনও কারণ নয়।
পিডিআর

1
@ এসভিক সঠিক, এ কারণেই এটি সাধারণত একটি সংকলক সতর্কতা। তবে "নতুন" করার দক্ষতা প্রান্ত শর্তগুলি (যেমন প্রদত্ত এক হিসাবে) কভার করে এবং আরও ভাল করে তোলে, এটি সত্যই স্পষ্ট করে তোলে যে আপনি যখন অনিবার্য ত্রুটিটি সনাক্ত করতে আসেন তখন আপনি অদ্ভুত কিছু করছেন। "কেন এই শ্রেণিটি এবং কেবল এই শ্রেণীর বগি ... আহ-হাহ, একটি" নতুন ", আসুন পরীক্ষা করা যাক যেখানে সুপার ক্লাস ব্যবহৃত হয়"।
ডিফোরে

7

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

এটি রানটাইমকে সহজতর করে তবে কিছু দুর্ভাগ্যজনক সমস্যা তৈরি করতে পারে। ধরা যাক GrafBaseবাস্তবায়ন হয় না void DrawParallelogram(int x1,int y1, int x2,int y2, int x3,int y3), তবে GrafDerivedএটি একটি সর্বজনীন পদ্ধতি হিসাবে প্রয়োগ করে যা একটি সমান্তরালঙ্ক আঁকে যার গণনা করা চতুর্থ বিন্দু প্রথমটির বিপরীতে। ধরুন, পরবর্তী সংস্করণ GrafBaseএকই স্বাক্ষর সহ একটি সার্বজনীন পদ্ধতি প্রয়োগ করে তবে এটির দ্বিতীয়টি বিপরীতে এর গণনা করা চতুর্থ বিন্দু। গ্রাহকরা যা প্রত্যাশা করেন GrafBaseতবে একটি রেফারেন্স পান তারা নতুন পদ্ধতির ফ্যাশনে সামনের দিকটি গণনা করার GrafDerivedপ্রত্যাশা DrawParallelogramকরবেন GrafBaseতবে যে ক্লায়েন্টরা GrafDerived.DrawParallelogramবেস পদ্ধতিটি পরিবর্তনের আগে ব্যবহার করছেন তারা GrafDerivedমূলত বাস্তবায়িত আচরণের প্রত্যাশা করবেন ।

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

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

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


2
আমি মনে করি এখানে একটি ভাল উত্তর আছে, তবে এটি পাঠ্যের দেয়ালে হারিয়ে যাচ্ছে। দয়া করে এটিকে আরও কয়েকটি অনুচ্ছেদে বিভক্ত করুন।
ববসন

DerivedGraphics? A class using গ্রাফডেরিভড কী ?
সি চ্যাম্পাগনে

@ সি GrafDerived। শ্যাম্পাগেন: আমি বলতে চাইছি । আমি ব্যবহার শুরু করেছি DerivedGraphics, তবে অনুভব করেছি এটি বেশ দীর্ঘ was এমনকি GrafDerivedএখনও কিছুটা দীর্ঘ, তবে গ্রাফিক্স-রেন্ডারারের প্রকারের নাম কীভাবে দেওয়া উচিত তার স্পষ্ট বেস / উত্সর্গীকৃত সম্পর্ক থাকতে হবে তা জানতেন না।
সুপারক্যাট

1
@ সাবসন: আরও ভাল?
supercat

6

মানক পরিস্থিতি:

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

বিশেষত, এটিকে অ-ওভারড্রাইয়েবল হিসাবে ঘোষণা না করে, আপনি স্পষ্টতই ঘোষণা করেছেন যে তারা এখন আপনার পরিবর্তনকে বাধা দেয় এমন কাজটি করতে ঠিক আছে।

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

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

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

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


0

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

সি # তে বেস শ্রেণির বিকাশকারী সাবক্লাস বিকাশকারীকে বিশ্বাস করে না। জাভাতে সাবক্লাস বিকাশকারী বেস ক্লাস বিকাশকারীকে বিশ্বাস করে না। সাবক্লাস বিকাশকারী সাবক্লাসের জন্য দায়বদ্ধ এবং তাদের (যথাযথ অস্বীকার ব্যতীত এবং জাভাতেও তারা এই ভুলটি পেতে পারে) দেখতে বেস ক্লাসটি বাড়ানোর ক্ষমতা দেওয়া উচিত (imho)।

এটি ভাষার সংজ্ঞা একটি মৌলিক সম্পত্তি। এটি সঠিক বা ভুল নয়, এটি যা হয় এবং তা পরিবর্তন করতে পারে না।


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