জনসাধারণের সদস্যদের কখনই ভার্চুয়াল / বিমূর্ত না করে - সত্যই?


20

২০০০ এর দশকে আমার এক সহকর্মী আমাকে বলেছিলেন যে পাবলিক পদ্ধতিগুলি ভার্চুয়াল বা বিমূর্ত করার পক্ষে এটি একটি বিরোধী-নিদর্শন।

উদাহরণস্বরূপ, তিনি এমন একটি শ্রেণি বিবেচনা করেছেন যা এটির নকশা ভাল নয়:

public abstract class PublicAbstractOrVirtual
{
  public abstract void Method1(string argument);

  public virtual void Method2(string argument)
  {
    if (argument == null) throw new ArgumentNullException(nameof(argument));
    // default implementation
  }
}

তিনি বলেছেন যে

  • একটি উদ্ভূত শ্রেণীর বিকাশকারী যা প্রয়োগ Method1এবং ওভাররাইডগুলি Method2যুক্তির বৈধতা পুনরুদ্ধার করতে হয়।
  • বেস শ্রেণীর বিকাশকারী Method1বা তার Method2পরে কাস্টমাইজযোগ্য অংশের কিছু যুক্ত করার সিদ্ধান্ত নিলে সে এটি করতে পারে না cannot

পরিবর্তে আমার সহকর্মী এই পদ্ধতির প্রস্তাব করেছিলেন:

public abstract class ProtectedAbstractOrVirtual
{
  public void Method1(string argument)
  {
    if (argument == null) throw new ArgumentNullException(nameof(argument));
    this.Method1Core(argument);
  }

  public void Method2(string argument)
  {
    if (argument == null) throw new ArgumentNullException(nameof(argument));
    this.Method2Core(argument);
  }

  protected abstract void Method1Core(string argument);

  protected virtual void Method2Core(string argument)
  {
    // default implementation
  }
}

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

তবে আমি এটিকে ডিজাইনের গাইডলাইন হিসাবে দেখছি না। মাইক্রোসফ্টও এটি অনুসরণ করে না: এটি Streamযাচাই করার জন্য ক্লাসটি একবার দেখুন ।

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


5
পদ্ধতিগুলি তৈরি করা virtual alচ্ছিক ওভাররাইডের অনুমতি দেয়। আপনার পদ্ধতি সম্ভবত সর্বজনীন হওয়া উচিত, কারণ এটি ওভাররাইড নাও হতে পারে। পদ্ধতি তৈরি abstract আপনাকে সেগুলি ওভাররাইড করতে বাধ্য করে; তাদের সম্ভবত হওয়া উচিত protected, কারণ তারা একটি publicপ্রসঙ্গে বিশেষভাবে কার্যকর নয় ।
রবার্ট হার্ভে

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

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

8
@ গ্রেগবার্গার্ড: শব্দগুলি ওপির সহকর্মী সর্বদা টেম্পলেট পদ্ধতির প্যাটার্নটি ব্যবহার করার পরামর্শ দেয় , তার প্রয়োজন বা না থাকুক। এটি নিদর্শনগুলির একটি সাধারণ অতিরিক্ত ব্যবহার - যদি কোনও হাতুড়ি থাকে, তাড়াতাড়ি বা পরে প্রতিটি সমস্যা পেরেকের মতো দেখতে শুরু করে ;-)
ডক ব্রাউন

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

উত্তর:


30

উক্তি

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

কারণ এবং প্রভাব মিশ্রিত করা হয়। এটি ধরে নেওয়া যায় যে প্রতিটি ওভাররাইডযোগ্য পদ্ধতিতে একটি অ-অনুকূলিতযোগ্য আর্গুমেন্ট বৈধতা প্রয়োজন। তবে এটি পুরোপুরি অন্যভাবে:

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

তবে এমন অনেকগুলি উদাহরণ রয়েছে যেখানে জনসাধারণের ভার্চুয়াল পদ্ধতিটি নিখুঁতভাবে উপলব্ধি করে, যেহেতু কোনও স্থির অ-অনুকূলিতকরণযোগ্য অংশ নেই: স্ট্যান্ডার্ড পদ্ধতিগুলি দেখুন ToStringবা Equalsবা GetHashCode- এটি objectক্লাসের নকশাটিকে পাবলিক না করার জন্য উন্নতি করবে এবং ভার্চুয়াল একই সাথে? আমি তাই মনে করি না.

অথবা, আপনার নিজের কোডের ক্ষেত্রে: যখন বেস ক্লাসের কোডটি শেষ অবধি এবং ইচ্ছাকৃতভাবে এর মতো দেখায়

 public void Method1(string argument)
 {
    // nothing to validate here, all strings including null allowed
    this.Method1Core(argument);
 }

এর মধ্যে এই বিচ্ছেদ থাকা Method1এবং Method1Coreকোনও আপাত কারণ ছাড়াই জিনিসগুলিকে জটিল করে তোলে।


1
ToString()পদ্ধতির ক্ষেত্রে মাইক্রোসফ্ট আরও ভালভাবে এটি অ-ভার্চুয়াল তৈরি করেছিল এবং একটি ভার্চুয়াল টেম্পলেট পদ্ধতি চালু করেছিল ToStringCore()। কেন: এর কারণে: ToString()- উত্তরাধিকারীদের কাছে নোট করুন । তারা জানায় যে বাতিল করা ToString()উচিত নয়। বাস্তবায়নের মাধ্যমে তারা এই দাবিতে জোর করতে পারত ToString() => ToStringCore() ?? string.Empty
পিটার পেরোট

9
@ পিটারপ্রোট: যে নির্দেশিকাটি আপনি সংযুক্ত করেছেন সেগুলিও ফিরে না আসার পরামর্শ দেয় string.Empty, আপনি কি লক্ষ্য করেছেন? এবং এটি এমন অনেকগুলি বিষয় প্রস্তাব দেয় যা কোনও ToStringCoreপদ্ধতির মতো কিছু প্রবর্তন করে কোডে প্রয়োগ করা যায় না । সুতরাং এই কৌশলটি সম্ভবত সঠিক সরঞ্জাম নয় ToString
ডক ব্রাউন

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

1
@ পিটারপেরোট "আমি" এর anyObjectIGot.ToString()পরিবর্তে অনেকগুলি কোড দেখেছি anyObjectIGot?.ToString()"- এটি কীভাবে প্রাসঙ্গিক? আপনার ToStringCore()দৃষ্টিভঙ্গি নাল স্ট্রিংটি ফিরে আসা আটকাবে, তবে NullReferenceExceptionবস্তুটি শূন্য হলে এটি একটি নিক্ষেপ করবে ।
IMIL

1
@ পিটারপেরোট আমি কর্তৃপক্ষের কাছ থেকে কোন যুক্তি প্রকাশ করার চেষ্টা করছিলাম না। এটি মাইক্রোসফ্ট যে পরিমাণে ব্যবহার করে তা তেমন কিছু নয় public virtual, তবে এমন কিছু ক্ষেত্রে রয়েছে যা public virtualঠিক আছে। কোডটি ভবিষ্যতের প্রমাণ হিসাবে খালি অ-অনুকূলিতযোগ্য অংশের জন্য আমরা তর্ক করতে পারি ... তবে এটি কার্যকর হয় না। ফিরে গিয়ে এটিকে পরিবর্তন করলে উদ্ভূত প্রকারগুলি ভেঙে যেতে পারে। সুতরাং, এটি কিছুই উপার্জন করে।
থেরোট

6

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

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

এটি বাস্তবায়নের নামকরণ কনভেনশন হ'ল (যা আমি জানি) জনসাধারণের ইন্টারফেসের জন্য ভাল নাম সংরক্ষণ করা এবং অভ্যন্তরীণ পদ্ধতির নামটিকে "কর" দিয়ে উপস্থাপন করা।

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


1
কি পদ্ধতি উপসর্গ এক বিকল্প। মাইক্রোসফ্ট প্রায়শই মূল পদ্ধতি পোস্টফিক্স ব্যবহার করে ।
পিটার পেরোট

@ পিটার পেরোট আমি কোনও মাইক্রোসফ্ট উপাদানে কোর উপসর্গটি কখনও দেখিনি তবে এটি হতে পারে কারণ আমি ইদানীং খুব বেশি মনোযোগ দিচ্ছি না। আমার সন্দেহ হয় তারা সম্প্রতি কোর মনিকারকে প্রচার করতে,। নেট কোরের নাম লেখানোর জন্য এটি করা শুরু করেছিল suspect
মার্টিন মাট 13

না, এটা একটি পুরানো টুপি আছে: BindingList। এছাড়াও আমি কোথাও এই প্রস্তাবটি পেয়েছি, সম্ভবত তাদের ফ্রেমওয়ার্ক ডিজাইনের গাইডলাইনস বা অনুরূপ কিছু। এবং: এটি একটি পোস্টফিক্স । ;-)
পিটার পেরোট

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

2

সি ++ এ একে নন-ভার্চুয়াল ইন্টারফেস প্যাটার্ন (এনভিআই) বলা হয়। (একসময় একে টেমপ্লেট পদ্ধতি বলা হত That এটি বিভ্রান্তিকর ছিল, তবে কিছু পুরানো নিবন্ধে সেই পরিভাষা রয়েছে)) এনভিআইয়ের প্রচার করেছেন হার্ব সুতার, যিনি এটি সম্পর্কে কমপক্ষে কয়েকবার লিখেছিলেন। আমার মনে হয় প্রথম দিকের একজন এখানে আছে

আমি যদি সঠিকভাবে স্মরণ করি তবে অনুমানটি হ'ল একটি উত্পন্ন শ্রেণীর উচিত না যে বেস ক্লাসটি কী করে কিন্তু এটি কীভাবে তা করে।

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

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

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

বেস ক্লাসটি ভোক্তাদের দ্বারা ব্যবহৃত পাবলিক ইন্টারফেসকে সংজ্ঞায়িত করে এবং এটি আদিম ক্রিয়াকলাপগুলির একটি ইন্টারফেসকে সংজ্ঞায়িত করে যে এটি public পাবলিক পদ্ধতিগুলি প্রয়োগ করতে হবে। উদ্ভূত প্রকারগুলি সেই সমস্ত আদিম ক্রিয়াকলাপ বাস্তবায়নের জন্য দায়ী।

C # এবং C ++ এর মধ্যে কোনও পার্থক্য সম্পর্কে অবগত নই যা শ্রেণি নকশার এই দিকটি বদলে দেবে।


গুড ফাইন্ড! এখন আমার মনে আছে আমি ঠিক সেই পোস্টটি খুঁজে পেয়েছিলাম আপনার ২ য় লিঙ্কটি পয়েন্টগুলি (বা এর একটি অনুলিপি), 2000 এর দশকে ফিরে এসেছিল। আমার মনে আছে আমি আমার সহকর্মীর দাবির আরও প্রমাণ খুঁজছিলাম, এবং আমি সি # প্রসঙ্গে কিছু খুঁজে পাইনি, তবে সি ++ পেয়েছি। এই. হয়। It চালু করুন! :-) তবে, সি # জমিতে ফিরে দেখে মনে হচ্ছে এই প্যাটার্নটি খুব বেশি ব্যবহৃত হয়নি। সম্ভবত লোকেরা বুঝতে পেরেছিল যে পরে বেস কার্যকারিতা যুক্ত করা উদ্ভূত শ্রেণিগুলিকেও ভেঙে ফেলতে পারে এবং জনসাধারণের ভার্চুয়াল পদ্ধতির পরিবর্তে টিএমপি বা এনভিআইপি ব্যবহারের কঠোর ব্যবহার সর্বদা তাৎপর্যপূর্ণ নয়।
পিটার পেরোট

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