আমি কেন সি # তে বিমূর্ত স্থির পদ্ধতিগুলি রাখতে পারি না?


181

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


3
ভবিষ্যতের উন্নতির জন্য দয়া করে এগুলিকে ছেড়ে দিন।
মার্ক বাইক

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

@ উইলিয়াম জকুছ রিসিভ টাইপ মানে কি? যদি আমি বেসক্লাস.স্ট্যাটিকমিথড () কল করি তবে বেসক্লাসই একমাত্র টাইপ যা সিদ্ধান্ত নিতে ব্যবহার করতে পারে। তবে এই স্তরে এটি বিমূর্ত তাই পদ্ধতিটি সমাধান করা যায় না। আপনি যদি পরিবর্তে ডেরিভডক্লাস.স্ট্যাটিকমথোডকে কল করেন তবে বেস শ্রেণিটি অপ্রাসঙ্গিক।
মার্টিন ক্যাপোডিসি

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

উত্তর:


156

স্থির পদ্ধতিগুলি যেমন ইনস্ট্যান্ট হয় না , সেগুলি কেবল কোনও অবজেক্টের রেফারেন্স ছাড়াই উপলব্ধ।

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

একটি উদাহরণ দেখা যাক।

নিম্নলিখিত কোড সহ:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

আপনি যদি B.Test কল করেন তবে এটি পছন্দ করুন:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

তারপরে মূল পদ্ধতির অভ্যন্তরীণ কোডটি নিম্নরূপ:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

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

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

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

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

সুতরাং, ভার্চুয়াল / বিমূর্ত স্ট্যাটিক পদ্ধতি .NET তে উপলব্ধ নেই।


4
সি # তে অপারেটর-ওভারলোডিং যেভাবে করা হচ্ছে তার সাথে একত্রে, দুর্ভাগ্যক্রমে একটি প্রদত্ত অপারেটর ওভারলোডের জন্য একটি বাস্তবায়ন সরবরাহ করার জন্য সাবক্লাসগুলির প্রয়োজনের সম্ভাবনাটি হ্রাস করে।
ক্রিস মোসচিনি

23
আমি এই উত্তর সংজ্ঞা যেমন ভয়ঙ্কর দরকারী এর খুঁজে না Test()হয় Aবিমূর্ত এবং সম্ভাব্য সংজ্ঞায়িত হওয়ার পরিবর্তে B\।

5
জেনেরিক ধরণের প্যারামিটারগুলি কার্যকরভাবে অ-অবিচলিত "টাইপ" ভেরিয়েবল হিসাবে আচরণ করে এবং ভার্চুয়াল স্ট্যাটিক পদ্ধতিগুলি এ জাতীয় প্রসঙ্গে কার্যকর হতে পারে। উদাহরণস্বরূপ, যদি Carভার্চুয়াল স্ট্যাটিক CreateFromDescriptionফ্যাক্টরি পদ্ধতিতে কারও কাছে একটি টাইপ থাকে , তবে যে কোডটি একটি- Carকনস্ট্রেনড জেনেরিক টাইপ গ্রহণ করেছে, তার ধরণের গাড়ি উত্পাদন Tকরতে কল T.CreateFromDescriptionকরতে পারে T। এই জাতীয় কাঠামোটি সিএলআরের অভ্যন্তরে বেশ ভালভাবে সমর্থিত হতে পারে যদি এই ধরণের পদ্ধতির সংজ্ঞা দেওয়া প্রতিটি ধরণের যদি কোনও ভার্চুয়াল "স্ট্যাটিক" পদ্ধতি ধারণ করে এমন কোনও নেস্টেড ক্লাস জেনেরিকের একটি স্ট্যাটিক সিঙ্গলটন উদাহরণ রাখে।
সুপারক্যাট

45

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

ধরে নিন আপনি এক মুহুর্তের জন্য স্থির পদ্ধতি অর্জন করতে পারেন। এই দৃশ্যটি কল্পনা করুন:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

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


33
আপনার দৃশ্যের প্রেক্ষিতে আমি বলব বেস.গেটনম্বার () 5 এ ফিরে আসবে; চাইল্ড 1. গেট নাম্বার () 1 প্রদান করে; চাইল্ড 2. গেট নাম্বার () 2 টি রিটার্ন করেছে; আপনার যুক্তি বুঝতে আমাকে সহায়তা করতে আপনি আমাকে ভুল প্রমাণ করতে পারেন? আপনাকে ধন্যবাদ
লুইস ফিলিপ

আপনি যে মুখটিকে বেস মনে করেন বলে মনে করে et বেস মানটি ফিরিয়ে দিয়ে, কোনও উত্তরাধিকার চলছে না।
ডেভিড ওয়েঙ্গিয়ার

60
বিশ্বে কেন বেস.গেটনम्बर () 5 ছাড়া আর কিছু ফেরত দেবে? এটি বেস শ্রেণিতে একটি পদ্ধতি - সেখানে কেবলমাত্র 1 টি বিকল্প রয়েছে।
আর্টেম রাশাকোভস্কিই

4
@ আর্টেমরুসাকোভস্কিই: ধরুন একজনের কাছে আছে int DoSomething<T>() where T:Base {return T.GetNumber();}DoSomething<Base>()পাঁচটি ফিরতে পারলে এটি কার্যকর বলে মনে হচ্ছে , DoSomething<Child2>()আবার দু'জন ফিরে আসবে। এই ধরনের ক্ষমতা কেবল খেলনা উদাহরণের জন্যই কার্যকর হবে না, তবে এমন কোনও class Car {public static virtual Car Build(PurchaseOrder PO);}কিছুর জন্যও যেখানে প্রতিটি শ্রেণি থেকে প্রাপ্ত Carএকটি শ্রেণিকে একটি ক্রয়ের অর্ডার দিয়ে একটি উদাহরণ তৈরি করতে পারে এমন একটি পদ্ধতি নির্ধারণ করতে হবে।
সুপারক্যাট

4
স্থিতিশীল উত্তরাধিকার নিয়ে ঠিক একই "সমস্যা" রয়েছে।
অর্ক-কুন

18

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

এর আগে জাভা এবং সি ++ এর মতো সি # তেমন ভাষা নয়; staticশব্দ বোঝাতে যে পদ্ধতি স্ট্যাটিক্যালি-আবদ্ধ হয় বদলে গতিশীল / ভার্চুয়াল স্পষ্টভাবে ব্যবহার করা হয়।


9

এখানে এমন পরিস্থিতি রয়েছে যেখানে স্থির ক্ষেত্র এবং পদ্ধতিগুলির জন্য উত্তরাধিকারের অবশ্যই প্রয়োজন আছে:

abstract class Animal
{
  protected static string[] legs;

  static Animal() {
    legs=new string[0];
  }

  public static void printLegs()
  {
    foreach (string leg in legs) {
      print(leg);
    }
  }
}


class Human: Animal
{
  static Human() {
    legs=new string[] {"left leg", "right leg"};
  }
}


class Dog: Animal
{
  static Dog() {
    legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
  }
}


public static void main() {
  Dog.printLegs();
  Human.printLegs();
}


//what is the output?
//does each subclass get its own copy of the array "legs"?

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

legsএকটি স্থির বিমূর্ত সম্পত্তি হতে হবে।
ছোট এন্ডিয়ান

8

পূর্বের ব্যাখ্যায় যুক্ত করতে, স্থির পদ্ধতি কলগুলি সংকলন-সময়ে একটি নির্দিষ্ট পদ্ধতির সাথে আবদ্ধ থাকে , যা পলিমারফিক আচরণকে বাতিল করে দেয়।


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

সুতরাং আপনি কীভাবে ভাবছেন যে সিএমআরতে পলিমারফিজম কাজ করে? আপনার ব্যাখ্যাটি সবেমাত্র ভার্চুয়াল পদ্ধতি প্রেরণের বিষয়টি বাতিল করে দিয়েছে।
রাইটমিস

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

দুঃখিত, আমি একটি অপমান বোঝাতে চাই নি (যদিও আমি কিছু চটজলদি সাড়া দিতে স্বীকার করি ;-)। আমার প্রশ্নের মূল বক্তব্যটি ছিল, আপনি যদি এই ক্লাসগুলি পেয়ে থাকেন: ক্লাস বেস {পাবলিক ভার্চুয়াল শূন্য পদ্ধতি (); } শ্রেণি উত্পন্ন: বেস {পাবলিক ওভাররাইড শূন্য পদ্ধতি (); } এবং এভাবে লিখুন: বেস উদাহরণ = নতুন উত্পন্ন (); instance.Method (); কল সাইটে সংকলন-টাইপ ধরণের তথ্য হ'ল আসল উদাহরণটি উত্পন্ন যখন আমরা বেসের একটি উদাহরণ পেয়েছি। সুতরাং সংকলক কল করার সঠিক পদ্ধতিটি সমাধান করতে পারে না। পরিবর্তে এটি "কলভার্ট" আইএল নির্দেশনা প্রকাশ করে যা রানটাইমকে প্রেরণে বলে দেয় ..
রাইটমিস

1
ধন্যবাদ মানুষ, তথ্যপূর্ণ! অনুমান করুন যে আমি ডুবটি IL তে দীর্ঘ দিন রেখে দিচ্ছি, আমার ভাগ্য কামনা করুন।
অ্যাডাম টলি

5

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

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

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

এটি কুরুচিপূর্ণ তবে প্রয়োজনীয়, এইভাবে আমরা প্রয়োজনীয় ক্লাসগুলি কেবল উপলভ্য অবজেক্টগুলির জন্য অনুসন্ধান করার জন্য ইনস্ট্যান্ট্যান্টেড না করে প্রয়োজনীয় যা প্রয়োজন তা কেবল ইনস্ট্যান্ট করতে পারি।

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

সুতরাং এটি প্রতিটি ক্লায়েন্টের জন্য একটি পৃথক সার্ভার অ্যাপ্লিকেশন থাকার চেয়ে বজায় রাখা অনেক সহজ।

আশা করি উদাহরণটি পরিষ্কার ছিল।


0

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


1
-1 ভার্চুয়াল পদ্ধতিতে কোনও নকশা বাদে উদাহরণের প্রয়োজন হয় না। এবং আপনি প্রকৃতপক্ষে প্রশ্নটির দিকে লক্ষ্য রাখবেন না, যতটা এটিকে অপসারণ করবেন।
ফ্যালান অবতার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.