প্রোগ্রামিং ভাষা কেন ভেরিয়েবল এবং ফাংশনগুলির ছায়া / গোপনের অনুমতি দেয়?


31

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

আমার কাছে লুকিয়ে থাকা এবং ছায়াময় করা অস্বীকার করা ভাল বলে মনে হয়।

কেউ কি এই ধারণাগুলির ভাল ব্যবহার সম্পর্কে জানেন?

আপডেট:
আমি শ্রেণি সদস্যদের (ব্যক্তিগত / সুরক্ষিত সদস্য) এর এনক্যাপসুলেশনকে উল্লেখ করছি না।


এজন্য আমার সমস্ত ক্ষেত্রের নাম এফ দিয়ে শুরু হবে
পিটার বি

7
আমি মনে করি এরিক লিপার্টের এ সম্পর্কে একটি দুর্দান্ত নিবন্ধ ছিল। ওহ অপেক্ষা করুন, এখানে এটা: blogs.msdn.com/b/ericlippert/archive/2008/05/21/...
Lescai Ionel

1
আপনার প্রশ্নটি পরিষ্কার করুন। আপনি কি সাধারণভাবে তথ্য গোপন করার বিষয়ে জিজ্ঞাসা করছেন, বা লিপার্ট নিবন্ধে বর্ণিত নির্দিষ্ট কেস সম্পর্কে জিজ্ঞাসা করছেন যেখানে একটি উত্পন্ন শ্রেণি বেস শ্রেণির ফাংশনগুলি গোপন করে?
অ্যারন কুর্তজল

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

উত্তর:


26

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

এটি স্থানীয় ভেরিয়েবল বা ফাংশনগুলি যে বিশ্বব্যাপী ভেরিয়েবল বা ক্রিয়াকলাপগুলি আড়াল করতে পারে তার চেয়ে বেশি পরিষ্কার clearly

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

মৌলিক সমস্যাটি লুকিয়ে / ছায়াযুক্ত নয়, তবে বৈশ্বিক চলক।


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

19
"আপনি যদি লুকোচুরি এবং ছায়াময় করা অস্বীকার করেন, আপনার কাছে যা আছে তা এমন ভাষা যা সমস্ত ভেরিয়েবল বৈশ্বিক।" - অগত্যা নয়: আপনার ছায়া ছাড়াই স্কোপড ভেরিয়েবল থাকতে পারে এবং আপনি এটি ব্যাখ্যা করেছেন।
থিয়াগো সিলভা

@ThiagoSilva: এবং তারপর আপনার ভাষা একটি উপায় এই মডিউল যে কম্পাইলার জানাতে হবে আছে হয় অ্যাক্সেস করতে পারবে মডিউল এর "frammis" পরিবর্তনশীল যে। আপনি কি এমন কাউকে এমন কোনও বিষয় লুকিয়ে রাখার / ছায়া দেওয়ার অনুমতি দিচ্ছেন যা তিনি জানেন না এমনকি এটি বিদ্যমান নেই, বা আপনি তাকে এই নামটি কেন ব্যবহার করার অনুমতি দিচ্ছেন না তা বলার জন্য?
জন আর স্ট্রোহম

9
@ ফিল, আপনার সাথে মতবিরোধের জন্য আমাকে ক্ষমা করবেন, তবে ওপি "ভেরিয়েবল বা ফাংশনগুলি আড়াল / ছায়া" সম্পর্কে জিজ্ঞাসা করেছিল, এবং "অভিভাবক", "শিশু", "শ্রেণি" এবং "সদস্য" শব্দটি তাঁর প্রশ্নের কোথাও পাওয়া যায় না। এটি এটিকে নামের সুযোগ সম্পর্কে একটি সাধারণ প্রশ্ন করে তোলে।
জন আর স্ট্রোহম

3
@ অডিএনএমসি, আমি হুইপারস্পেনার যুবকের পক্ষে "2001: একটি স্পেস ওডিসি" রেফারেন্স না পাওয়ার পক্ষে যথেষ্ট যুবকের মুখোমুখি হওয়ার পক্ষে দীর্ঘসময় বেঁচে থাকার আশা করিনি।
জন আর স্ট্রোহম

15

কেউ কি এই ধারণাগুলির ভাল ব্যবহার সম্পর্কে জানেন?

নির্ভুল, বর্ণনামূলক শনাক্তকারীদের ব্যবহার সর্বদা একটি ভাল ব্যবহার।

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

ক্ষেত্রের বনাম স্থানীয় ভেরিয়েবলগুলি পার্থক্যের জন্য এক ধরণের হবিশী স্বরলিপি ব্যবহার করে এটি প্রায় পাওয়া যায় তবে রক্ষণাবেক্ষণের (এবং প্রোগ্রামার স্যানিটি) তার নিজস্ব প্রভাব রয়েছে।

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


3
আসলে, না, লুকানো এবং ছায়া কাটা কার্যকর করা সহজ নয়। "সমস্ত ভেরিয়েবলগুলি বিশ্বব্যাপী" প্রয়োগ করা আসলেই সহজ। আপনার কেবলমাত্র একটি নেমস্পেস প্রয়োজন এবং একাধিক নেমস্পেস থাকা এবং প্রতিটি নাম এটি রফতানি করতে হবে কিনা তা সিদ্ধান্ত নেওয়ার বিপরীতে আপনি সর্বদা নামটি রফতানি করেন।
জন আর স্ট্রোহম

5
@ জনআর.স্ট্রোহম - অবশ্যই, তবে যত তাড়াতাড়ি আপনার কোনও ধরণের স্কোপিং রয়েছে (পড়ুন: শ্রেণিগুলি) তারপরে স্কোপগুলি নীচের স্কোপগুলি আড়াল করে রাখা বিনামূল্যে is
টেলাস্টিন

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

@ মিমিকশাল - অবশ্যই আমার আরও পরিষ্কার হওয়া উচিত ছিল।
টেলাস্টিন

7

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

কেন এটি মঞ্জুরি দেওয়া হয়েছে তার সংক্ষিপ্ত উত্তর হ'ল এটি না করা বিকাশকারীদের অবজেক্ট-ওরিয়েন্টেড ডিজাইনের বিভিন্ন মূল নীতি লঙ্ঘন করতে বাধ্য করবে।

এখানে দীর্ঘ উত্তর; প্রথমে বিকল্প মহাবিশ্বে নিম্নলিখিত শ্রেণীর কাঠামোটি বিবেচনা করুন যেখানে সি # সদস্যকে লুকানোর অনুমতি দেয় না:

public interface IFoo
{
   string MyFooString {get;}
   int FooMethod();
}

public class Foo:IFoo
{
   public string MyFooString {get{return "Foo";}}
   public int FooMethod() {//incredibly useful code here};
}

public class Bar:Foo
{
   //public new string MyFooString {get{return "Bar";}}
}

আমরা বারে সদস্যকে অসন্তুষ্ট করতে চাই এবং এর মাধ্যমে বারকে একটি আলাদা মাইফুস্ট্রিং সরবরাহ করার অনুমতি দিন। তবে, আমরা এটি করতে পারি না কারণ এটি সদস্য গোপনে বিকল্প-বাস্তবতা নিষেধাজ্ঞার লঙ্ঘন করবে। এই বিশেষ উদাহরণটি বাগগুলির জন্য কার্যকর হবে এবং আপনি কেন এটি নিষিদ্ধ করতে চাইতে পারেন তার একটি প্রধান উদাহরণ; উদাহরণস্বরূপ, আপনি নিম্নলিখিতটি করলে কোন কনসোল আউটপুট পাবেন?

Bar myBar = new Bar();
Foo myFoo = myBar;
IFoo myIFoo = myFoo;

Console.WriteLine(myFoo.MyFooString);
Console.WriteLine(myBar.MyFooString);
Console.WriteLine(myIFoo.MyFooString);

আমার মাথার শীর্ষে, আমি আসলে নিশ্চিত নই যে আপনি সেই শেষ লাইনে "ফু" বা "বার" পেয়েছেন কিনা। আপনি তিনটি ভেরিয়েবল একই অবস্থা হিসাবে ঠিক একই উদাহরণ হিসাবে উল্লেখ থাকলেও আপনি অবশ্যই প্রথম লাইনের জন্য "ফু" এবং দ্বিতীয়টির জন্য "বার" পেতে চাইবেন।

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

public class Bar:Foo
{
   public string MyBarString {get{return "Bar";}}       
}

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

আমরা বেশ প্রশংসনীয়ভাবে পিতামাতার সাথে সম্পর্কের কথা ভুলে গিয়ে সরাসরি ইন্টারফেসটি প্রয়োগ করতে পারি:

public class Bar:IFoo
{
   public string MyFooString {get{return "Bar";}}
   public int FooMethod() {...}
}

এই সাধারণ উদাহরণের জন্য এটি একটি নিখুঁত উত্তর, যতক্ষণ না আপনি কেবল খেয়াল রাখবেন যে ফু এবং বার উভয়ই আইফো। কয়েকটি উদাহরণ উদাহরণস্বরূপ ব্যবহার কোড সংকলন করতে ব্যর্থ হবে কারণ একটি বার কোনও ফু নয় এবং এরূপ হিসাবে বরাদ্দ করা যায় না। তবে, ফু এর কাছে বারের প্রয়োজনীয় কিছু কার্যকর পদ্ধতি "FooMethod" থাকলে এখন আপনি সেই পদ্ধতির উত্তরাধিকারী হতে পারবেন না; আপনাকে হয় বারে এর কোডটি ক্লোন করতে হবে, বা সৃজনশীল পেতে হবে:

public class Bar:IFoo
{
   public string MyFooString {get{return "Bar";}}
   private readonly theFoo = new Foo();

   public int FooMethod(){return theFoo.FooMethod();}
}

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

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

public class Foo:IFoo
{
   public virtual string MyFooString {get{return "Foo";}}
   //...
}

public class Bar:Foo
{
   public override string MyFooString {get{return "Bar";}}
}

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

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


আসল প্রশ্ন সম্বোধনের জন্য +1 এরিপ লিবারবার্টের ব্লগ পোস্টে এই বিষয়টিতে বর্ণিত সদস্য আড়াল করার আসল-বিশ্বের ব্যবহারের একটি ভাল উদাহরণ IEnumerableএবং IEnumerable<T>ইন্টারফেস ।
ফিল

অগ্রাহ্য করা হয় না গোপন। আমি @ ফিলের সাথে একমত নই যে এটি প্রশ্নের উত্তর দেয়।
জানু হুডেক

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

আমি আপনার ছায়া গোপন / লুকানোর ব্যবহার পছন্দ করি না। আমি যে প্রধান ভাল ব্যবহারগুলি দেখছি সেগুলি হল (1) পরিস্থিতিটির চারপাশে কিলজিলিং যেখানে বেস ক্লাসের নতুন সংস্করণে এমন কোনও সদস্য অন্তর্ভুক্ত থাকে যা পুরানো সংস্করণ [কুরুচিপূর্ণ তবে প্রয়োজনীয়] এর আশেপাশে ডিজাইন করা গ্রাহক কোডের সাথে বিরোধ করে; (২) রিটার্ন-টাইপ কোভেরিয়েন্সের মতো জিনিস নকল করা; (3) ক্ষেত্রে যেখানে একটি বেস ক্লাসের পদ্ধতি সঙ্গে তার আচরণ callable একটি নির্দিষ্ট উপপ্রকার কিন্তু না দরকারী । এলএসপিতে প্রাক্তনটির প্রয়োজন হয় তবে বেসিক-শ্রেণির চুক্তিটি নির্দিষ্ট করে যে কিছু পরিস্থিতিতে কিছু পরিস্থিতিতে কার্যকর নাও হতে পারে তবে পরবর্তীটির প্রয়োজন হয় না।
সুপারক্যাট

2

সত্যই, সি # সংকলক দলের নীতিগত বিকাশকারী এরিক লিপার্ট খুব সুন্দরভাবে এটি ব্যাখ্যা করেছেন (লিঙ্কটির জন্য লেসকাই আয়নেলকে ধন্যবাদ)) .NET এর IEnumerableএবং IEnumerable<T>ইন্টারফেসগুলি যখন সদস্য লুকানো কার্যকর হয় তার একটি ভাল উদাহরণ।

.NET এর প্রথম দিনগুলিতে, আমাদের জেনেরিকস ছিল না। সুতরাং IEnumerableইন্টারফেসটি এরকম দেখাচ্ছে:

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

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

তারপরে জেনেরিকস এসেছিল। যখন আমরা জেনেরিকস পেয়েছি, তখন আমরা একটি নতুন ইন্টারফেসও পেয়েছি:

public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

এখন আমরা তাদের মাধ্যমে পুনরাবৃত্তি করার সময় অবজেক্টগুলি কাস্ট করতে হবে না! Woot! এখন, যদি সদস্য লুকানোর অনুমতি না দেওয়া হয়, তবে ইন্টারফেসটির জন্য এটির মতো কিছু দেখতে হবে:

public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumeratorGeneric();
}

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

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


আনুষ্ঠানিকভাবে IEnumerable<T>.GetEnumerator()আড়াল করার সময় IEnumerable.GetEnumerator(), এটি কেবল কারণ ওভাররাইড করার সময় সি # এর কোভেরিয়েন্ট রিটার্নের ধরণ নেই। যৌক্তিকভাবে এটি একটি ওভাররাইড, সম্পূর্ণরূপে এলএসপির সাথে সামঞ্জস্য। লুকানো হ'ল যখন আপনার mapফাইলের ফাংশনে লোকাল ভেরিয়েবল থাকে using namespace std(সি ++ তে)।
জানু হুডেক

2

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

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

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

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

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

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


2

এখানে আমার দুটি সেন্ট।

প্রোগ্রামগুলিকে ব্লকগুলিতে (ফাংশন, পদ্ধতি) কাঠামোবদ্ধ করা যায় যা প্রোগ্রাম লজিকের স্ব-অন্তর্ভুক্ত ইউনিট। প্রতিটি ব্লক নাম / সনাক্তকারী ব্যবহার করে "জিনিস" (ভেরিয়েবল, ফাংশন, পদ্ধতি) উল্লেখ করতে পারে। নাম থেকে জিনিসগুলিতে এই ম্যাপিংকে বাধ্যতামূলক বলা হয় ।

ব্লক দ্বারা ব্যবহৃত নামগুলি তিনটি বিভাগে পড়ে:

  1. স্থানীয়ভাবে সংজ্ঞায়িত নামগুলি, যেমন স্থানীয় ভেরিয়েবলগুলি, যা কেবলমাত্র ব্লকের ভিতরে পরিচিত।
  2. ব্লকটি যখন আহ্বান করা হয় তখন মানগুলির সাথে আবদ্ধ হওয়া যুক্তিগুলি and
  3. বাহ্যিক নাম / বাইন্ডিংগুলি যে পরিবেশে ব্লকটি অন্তর্ভুক্ত রয়েছে এবং ব্লকের মধ্যে রয়েছে সেগুলি সংজ্ঞায়িত করা হয়েছে।

উদাহরণস্বরূপ নিম্নলিখিত সি প্রোগ্রাম বিবেচনা করুন

#include<stdio.h>

void print_double_int(int n)
{
  int d = n * 2;

  printf("%d\n", d);
}

int main(int argc, char *argv[])
{
  print_double_int(4);
}

ফাংশনটির print_double_intএকটি স্থানীয় নাম (স্থানীয় পরিবর্তনশীল) d, এবং যুক্তি রয়েছে nএবং এটি বাহ্যিক, বৈশ্বিক নাম ব্যবহার করে printf, যা স্কোপে রয়েছে তবে স্থানীয়ভাবে সংজ্ঞায়িত হয়নি।

printfএকটি আর্গুমেন্ট হিসাবে পাস করা যেতে পারে তা লক্ষ্য করুন :

#include<stdio.h>

void print_double_int(int n, int printf(const char *, ...))
{
  int d = n * 2;

  printf("%d\n", d);
}

int main(int argc, char *argv[])
{
  print_double_int(4, printf);
}

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

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

উদাহরণস্বরূপ এই স্কালা কোডটি ধরুন:

object ClosureExample
{
  def createMultiplier(n: Int) = (m: Int) => m * n

  def main(args: Array[String])
  {
    val multiplier3 = createMultiplier(3)
    val multiplier5 = createMultiplier(5)

    // Prints 6.
    println(multiplier3(2))

    // Prints 10.
    println(multiplier5(2))
  }
}

ফাংশনের রিটার্ন মান createMultiplierহ'ল ক্লোজার (m: Int) => m * n, এতে যুক্তি mএবং বাহ্যিক নাম রয়েছে n। নামটি nপ্রসঙ্গটি পর্যবেক্ষণ করে সমাধান করা হয়েছে যেখানে ক্লোজারটি সংজ্ঞায়িত করা হয়েছে: নামটি nকার্যকারণের যুক্তির সাথে আবদ্ধ createMultiplier। লক্ষ্য করুন যে বন্ধনটি তৈরি হওয়ার সময় এই বাঁধাইটি তৈরি করা হয়েছে, অর্থাত্ যখন createMultiplierপ্রার্থনা করা হয়। সুতরাং নামটি nফাংশনটির একটি বিশেষ আহ্বানের জন্য আর্গুমেন্টের আসল মানের সাথে আবদ্ধ। এটি একটি লাইব্রেরির ক্রিয়াকলাপের সাথে এর বিপরীতে করুন printf, যা প্রোগ্রামের এক্সিকিউটেবলটি তৈরি হওয়ার পরে লিংক দ্বারা সমাধান করা হয়।

সংক্ষিপ্তসার হিসাবে, কোডের স্থানীয় ব্লকের ভিতরে বাহ্যিক নামগুলি উল্লেখ করা কার্যকর হতে পারে যাতে আপনি

  • বাহ্যিকভাবে সংজ্ঞায়িত নামগুলি আর্গুমেন্ট হিসাবে স্পষ্টভাবে পাস করার প্রয়োজন / চাই না and
  • কোনও ব্লক তৈরি হওয়ার পরে আপনি রানটাইমের সময়ে বাইন্ডিংগুলি হিমশীতল করতে পারেন এবং তারপরে ব্লকটি সঞ্চারিত হওয়ার পরে এটি অ্যাক্সেস করতে পারেন।

ছায়াছবি তখনই আসে যখন আপনি বিবেচনা করেন যে কোনও ব্লকে আপনি কেবলমাত্র পরিবেশের সাথে সংজ্ঞায়িত প্রাসঙ্গিক নামগুলিতে আগ্রহী, যেমন আপনি যে printfফাংশনটি ব্যবহার করতে চান তাতে। (সুযোগ দ্বারা আপনি একটি স্থানীয় নাম ব্যবহার করতে চান তাহলে getc, putc, scanf, ...) ইতিমধ্যে পরিবেশে ব্যবহার করা হয়েছে, আপনি সহজ চান উপেক্ষা করার (ছায়া) গ্লোবাল নাম। সুতরাং, স্থানীয়ভাবে চিন্তা করার সময় আপনি পুরো (সম্ভবত খুব বড়) প্রসঙ্গে বিবেচনা করতে চান না।

অন্য দিকে, বিশ্বব্যাপী চিন্তা করার সময়, আপনি স্থানীয় প্রেক্ষাপটের অভ্যন্তরীণ বিবরণ (এনক্যাপসুলেশন) উপেক্ষা করতে চান। অতএব আপনার ছায়াময় হওয়া দরকার, অন্যথায় বিশ্বব্যাপী নাম যুক্ত করা সেই নামটি ইতিমধ্যে ব্যবহার করা প্রতিটি স্থানীয় ব্লককে ভেঙে ফেলতে পারে।

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

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