কনস্ট্রাক্টর সাধারণত পদ্ধতি কল না করা উচিত


12

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

উদাহরণ (আমার মরিচা সি ++ এ)

class C {
public :
    C(int foo);
    void setFoo(int foo);
private:
    int foo;
}

C::C(int foo) {
    setFoo(foo);
}

void C::setFoo(int foo) {
    this->foo = foo
}

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

সম্পাদনা: আমি সাধারণভাবে কথা বলছি, তবে আমরা পাইথনে কোডিং করছি।


এটি কি সাধারণ নিয়ম বা নির্দিষ্ট ভাষার জন্য নির্দিষ্ট?
ক্রিসএফ

কোন ভাষা? সি ++ এ এটি একটি বিরোধী-নিদর্শনের চেয়ে বেশি: প্যারাসিফট.com
c

@ Lenny222, "বর্গ পদ্ধতি" সম্পর্কে ওপি আলোচনা, যা - আমাকে অন্তত - মানে অ উদাহরণস্বরূপ পদ্ধতি । যা ভার্চুয়াল হতে পারে না।
প্যাটার তারেক

3
@ আলবা জাভাতে এটি পুরোপুরি ঠিক আছে। আপনার যা করা উচিত নয় তা thisআপনি নির্মাতাদের কাছ থেকে কল করেছেন এমন কোনও পদ্ধতিতে স্পষ্টভাবে প্রেরণ করা হয়েছে।
বিজিকলপ

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

উত্তর:


26

আপনি কোন ভাষা নির্দিষ্ট করেন নি।

সি ++ এ কোনও ভার্চুয়াল ফাংশন কল করার সময় একজন কনস্ট্রাক্টরকে অবশ্যই সতর্ক থাকতে হবে, এতে যে প্রকৃত ফাংশনটি এটি কল করছে তা শ্রেণি বাস্তবায়ন। যদি এটি প্রয়োগ না করে খাঁটি ভার্চুয়াল পদ্ধতি হয় তবে এটি অ্যাক্সেস লঙ্ঘন হবে।

একজন কনস্ট্রাক্টর নন-ভার্চুয়াল ফাংশনগুলি কল করতে পারে।

আপনার ভাষা যদি জাভা হয় যেখানে ফাংশনগুলি সাধারণত ডিফল্টরূপে ভার্চুয়াল হয় তবে বোঝা যায় যে আপনাকে অতিরিক্ত সতর্কতা অবলম্বন করতে হবে।

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

কনস্ট্রাক্টরদের কাছ থেকে পদ্ধতি কল করার সাধারণ কারণ হ'ল আপনার কাছে একাধিক কনস্ট্রাক্টর রয়েছে যা একটি সাধারণ "init" পদ্ধতি কল করতে চান।

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

জাভা এবং সি # এর ডেস্ট্রাক্টর নেই, তাদের ফাইনালাইজার রয়েছে। জাভা নিয়ে আচরণ জানি না।

সি # এই ক্ষেত্রে সঠিকভাবে সাফ আপ পরিচালনা করতে উপস্থিত হবে।

(দ্রষ্টব্য যে জাভা এবং সি # তে আবর্জনা সংগ্রহ করা থাকলেও এটি কেবল মেমরির বরাদ্দকে পরিচালনা করে There এমন আরও একটি ক্লিন-আপ রয়েছে যা আপনার ধ্বংসকারীকে মেমরি ছেড়ে দেয় না এমনটি করা দরকার)।


13
এখানে কয়েকটি ছোট ত্রুটি রয়েছে। সি # তে থাকা পদ্ধতিগুলি ডিফল্টরূপে ভার্চুয়াল নয়। কনস্ট্রাক্টরে ভার্চুয়াল পদ্ধতিটি কল করার সময় সি # এর সি ++ এর চেয়ে আলাদা শব্দার্থক শব্দ রয়েছে; সর্বাধিক উদ্ভূত প্রকারের ভার্চুয়াল পদ্ধতিটি কল করা হবে, বর্তমানে নির্মিত ধরণের অংশটির ভার্চুয়াল পদ্ধতি নয়। সি # এর চূড়ান্তকরণের পদ্ধতিগুলিকে "ডেস্ট্রাক্টর" বলছে তবে আপনি ঠিক বলেছেন যে তাদের চূড়ান্তকরণের শব্দার্থকতা রয়েছে। সি # ডেস্ট্রাস্টারগুলিতে ডাকা ভার্চুয়াল পদ্ধতিগুলি কনস্ট্রাক্টরগুলির মতো একইভাবে কাজ করে; সর্বাধিক উদ্ভূত পদ্ধতি বলা হয়।
এরিক লিপার্ট

@ পিটার: আমি উদাহরণের পদ্ধতিগুলি লক্ষ্য করেছিলাম। বিভ্রান্তির জন্য দুঃখিত.
স্টেফানো বোরিনি

1
@ এরিক লিপার্ট সি # তে আপনার দক্ষতার জন্য আপনাকে ধন্যবাদ, আমি সেই অনুযায়ী আমার উত্তরটি সম্পাদনা করেছি। আমি সেই ভাষায় অজ্ঞাতসারে, আমি সি ++ খুব ভাল এবং জাভা কম ভাল জানি।
ক্যাশকো

5
আপনাকে স্বাগতম. নোট করুন যে সি # তে বেস ক্লাস কন্সট্রাক্টরে ভার্চুয়াল পদ্ধতিতে কল করা এখনও বেশ খারাপ ধারণা।
এরিক লিপার্ট

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

18

ঠিক আছে, এখন ক্লাস পদ্ধতি বনাম উদাহরণ পদ্ধতিগুলি সম্পর্কে বিভ্রান্তি পরিষ্কার হয়ে গেছে, আমি একটি উত্তর দিতে পারি :-)

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

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

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


3
(+1) "কনস্ট্রাক্টরের অভ্যন্তরে, অবজেক্টটি এখনও সম্পূর্ণরূপে নির্মিত হয়নি" " "ক্লাস পদ্ধতি বনাম উদাহরণ" হিসাবে একই। কিছু প্রোগ্রামিং লেঙ্গাগুলি ঠিকাদার হিসাবে প্রবেশের সময় এটি নির্মিত হিসাবে বিবেচনা করে, যদি প্রোগ্রামার যেখানে কনস্ট্রাক্টরকে মান নির্ধারণ করে।
ইউএমএলকেট

7

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

এখানে একটি নিবন্ধ যা কর্তৃপক্ষের জন্য আপনার আবেদনকে সন্তুষ্ট করতে সহায়তা করতে পারে: http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/

এটি কল করার পদ্ধতিগুলি সম্পর্কে আসলে নয়, তবে খুব বেশি নির্মাণকারী নির্মাণকারীদের সম্পর্কে। আইএমএইচও, কনস্ট্রাক্টরে কল করার পদ্ধতিগুলি এমন গন্ধ যা বোঝাতে পারে যে কোনও নির্মাণকারী খুব ভারী too

এটি আপনার কোড পরীক্ষা করা কত সহজ তা সম্পর্কিত related কারণগুলি অন্তর্ভুক্ত:

  1. ইউনিট টেস্টিংয়ে প্রচুর সৃষ্টি এবং ধ্বংস জড়িত - তাই নির্মাণ দ্রুত হওয়া উচিত।

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


3

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

প্রযুক্তিগতভাবে, এতে কিছু ভুল হতে পারে না, সি ++ এবং বিশেষত পাইথন-এ, সাবধান হওয়া আপনার বিষয়।

ব্যবহারিকভাবে, আপনার ক্লাসের সদস্যদের সূচনা করার জন্য কেবল এমন পদ্ধতিতে কলগুলি সীমাবদ্ধ করা উচিত।


2

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

বুদ্ধিমান ওওপি সমর্থন সহ যে ভাষাগুলিতে শুরু থেকে সঠিকভাবে ভেটেবল পয়েন্টার সেট করা আছে, এই সমস্যাটি বিদ্যমান নেই।


2

কোনও পদ্ধতি কল করার ক্ষেত্রে দুটি সমস্যা রয়েছে:

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

কোনও সহায়ক ফাংশন কল করার ক্ষেত্রে কোনও ভুল নেই, যতক্ষণ না এটি আগের দুটি ক্ষেত্রে না পড়ে।


1

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


বস্তুর সূচনা করুন।
স্টেফানো বোরিনি

@ স্টেফানো বোরিনী: কেমন? কোনও অবজেক্ট-ভিত্তিক সিস্টেমে আপনি কল করতে পারেন এমন একমাত্র কাজ। বা বিপরীত কোণ থেকে এটি তাকান: কল পদ্ধতিতে কিছু করা হয়। এবং "কিছু" স্পষ্টতই অবজেক্ট ইনিশিয়েশন অন্তর্ভুক্ত করে। সুতরাং, যদি, অবজেক্টটি আরম্ভ করার জন্য, আপনাকে পদ্ধতিগুলি কল করতে হবে, তবে কনস্ট্রাক্টররা পদ্ধতিগুলি কল করতে পারেন না, তবে কোনও কনস্ট্রাক্টর কীভাবে বস্তুটি আরম্ভ করতে পারে?
Jörg ডব্লু মিটাগ

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

@ স্টেফানো বোরিনি: "আপনি সরাসরি কোনও অবজেক্ট ছাড়াই রাষ্ট্রটির সূচনা করতে পারেন, সরাসরি আপনার অবজেক্টের অভ্যন্তরীণ জায়গায়"। দুঃখের বিষয়, যখন এর মধ্যে একটি পদ্ধতি জড়িত তখন আপনি কী করবেন? কোডটি অনুলিপি এবং অতীত?
এস .লট

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

0

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

সি ++ ও ডেলফি-তে, যদি আমাকে কিছু বৈশিষ্ট্যগুলিতে ("ক্ষেত্রের সদস্যদের") প্রাথমিক মান দিতে হত এবং কোডটি খুব প্রসারিত হয় তবে আমি কনস্ট্রাক্টরগুলির সম্প্রসারণ হিসাবে কিছু গৌণ পদ্ধতি যুক্ত করি add

এবং আরও জটিল স্টাফ করে এমন অন্যান্য পদ্ধতিগুলি বলবেন না।

বৈশিষ্ট্যগুলির "getters" এবং "setters" পদ্ধতি হিসাবে, আমি সাধারণত তাদের রাষ্ট্র সংরক্ষণের জন্য ব্যক্তিগত / সুরক্ষিত ভেরিয়েবল ব্যবহার করি, এবং "getters" এবং "সেটটার" পদ্ধতিগুলি।

কনস্ট্রাক্টরটিতে আমি বৈশিষ্ট্যগুলির রাজ্য ক্ষেত্রগুলিতে "ডিফল্ট" মানগুলি অর্পণ করি, "অ্যাকসেসর" না বলেই

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