বেস ক্লাসে বিমূর্ত সম্পত্তি প্রোগ্রামারকে এটি সংজ্ঞায়িত করতে বাধ্য করে


10

আমি এম্বেড থাকা ডিভাইসের জন্য একটি রাষ্ট্র প্যাটার্ন সহ কোডিং করছি। আমার স্টেট নামে একটি বেস / অ্যাবস্ট্রাক্ট ক্লাস রয়েছে এবং তারপরে প্রতিটি বিযুক্ত (কংক্রিট) রাষ্ট্র বর্গ বিমূর্ত স্টেট ক্লাস প্রয়োগ করে।

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

... ত্রুটি 1 'myConcreteState' উত্তরাধিকারসূত্রে বিমূর্ত বিমূর্ত সদস্য 'myAbstractState' প্রয়োগ করে না

এখন: আমি স্টেটনাম নামে প্রতিটি রাজ্যের জন্য একটি স্ট্রিং সম্পত্তি তৈরি করার চেষ্টা করছি। যখনই আমি একটি নতুন কংক্রিট শ্রেণি তৈরি করি, আমার স্টেটনামটি সংজ্ঞায়িত করতে হবে। আমি চাই যদি ভিএস এটি ব্যবহার না করে তবে একটি ত্রুটি নিক্ষেপ করবে। এটি করার কোন সহজ পথ আছে কি?

আমি এটি বিমূর্ত / বেস শ্রেণিতে চেষ্টা করেছি:

public abstract string StateName { get; set; }

তবে প্রতিটি রাজ্যে গেট অ্যান্ড সেট পদ্ধতিগুলি প্রয়োগ করার দরকার নেই।

সংশোধিত প্রশ্ন: একটি আদর্শ পরিস্থিতিতে প্রতিটি রাজ্য শ্রেণীর স্টেটনাম সংজ্ঞায়িত করা এবং বিমূর্ত বেস শ্রেণীর উত্তরাধিকার সূত্রে প্রাপ্ত হওয়া আবশ্যক।

StateName = "MyState1"; //or whatever the state's name is

যদি বিবৃতিটি অনুপস্থিত থাকে তবে ভিজ্যুয়াল স্টুডিও উপরে বর্ণিত হিসাবে ত্রুটি তৈরি করবে। এটি কি সম্ভব এবং যদি তাই হয় তবে কীভাবে?


2
আমি প্রশ্নটি বুঝতে পারি না।
বেন অ্যারনসন

আমি অনুমান করি যে এটি করার জন্য "সঠিক" উপায়টি বেস বর্গে একটি সুরক্ষিত কনস্ট্রাক্টর রাখা উচিত যার জন্য পরামিতি হিসাবে রাষ্ট্রের নাম প্রয়োজন।
রোমান রেইনার

@ রোমানরাইনার আমি সেই কাজটি করার বিষয়ে ভেবেছিলাম..কিন্তু এটি বিব্রতকর বলে মনে হয় কারণ প্রতিবার কোনও রাষ্ট্র পরিবর্তন / কল করার সময় আমার নাম লিখতে হবে।
গিসমফেক্স

@ বেনআরনসন আমি নীচে আমার প্রশ্নটি পরিষ্কার করে দিয়েছি।
গিসমফেক্স

প্রতি নাম অনুসারে রাষ্ট্রের নাম কি ধ্রুব বা প্রতি উদাহরণে ধ্রুব?
রোমান রেইনার

উত্তর:


16

আমি অনুমান করি যে এটি করার জন্য "সঠিক" উপায়টি বেস বর্গে একটি সুরক্ষিত কনস্ট্রাক্টর রাখা উচিত যার জন্য পরামিতি হিসাবে রাষ্ট্রের নাম প্রয়োজন।

public abstract class State
{
    private readonly string _name;

    protected State(string name)
    {
        if(String.IsNullOrEmpty(name))
            throw new ArgumentException("Must not be empty", "name");

        _name = name;
    }

    public string Name { get { return _name; } }
}

এর পরে কংক্রিটের রাজ্যগুলি এমন একটি পাবলিক কনস্ট্রাক্টর সরবরাহ করে যা যথাযথ নামে বেস শ্রেণির নির্মাতাকে ডাকে।

public abstract class SomeState : State
{
    public SomeState() : base("The name of this state")
    {
        // ...
    }
}

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

মনে রাখবেন যে আপনি যখন কোনও কংক্রিটের রাজ্য ইনস্ট্যান্ট করবেন তখন আপনাকে নাম সরবরাহ করার দরকার নেই কারণ এর নির্মাতা তার যত্ন নেন:

var someState = new SomeState(); // No need to define the name here
var name = someState.Name; // returns "The name of this state"

1
ধন্যবাদ! বাস্তবে, আমার বেস শ্রেণির নির্মাতা এখন একটি অতিরিক্ত যুক্তি নিয়েছেন; সুতরাং আমি দুটি ইনপুট আছে। এটি সেট করার সাথে সাথেই আমি ত্রুটিগুলি পেয়েছি যে আমার রাজ্য বর্গ নির্মাতাদের একটি অতিরিক্ত যুক্তি প্রয়োজন ...:base(arg1, arg2)! এটি এমন একটি সমাধান যা আমি সন্ধান করছিলাম। এটি আমার রাজ্য কোডিংকে আরও ধারাবাহিকভাবে রাখতে সহায়তা করে।
গিসমফেক্স

3

সি # 6 হিসাবে (আমি বিশ্বাস করি - সি #: নতুন এবং উন্নত সি # 6.0 ) আপনি কেবলমাত্র গেটর বৈশিষ্ট্য তৈরি করতে সক্ষম। সুতরাং আপনি যেমন আপনার বেস ক্লাস ঘোষণা করতে পারে -

public abstract class State
{
    public abstract string name { get; }

    // Your other functions....
}

এবং তারপরে আপনার সাব-ক্লাসে আপনি এর Stateমতো প্রয়োগ করতে পারবেন -

public class SomeState : State
{
    public override string name { get { return "State_1"; } }
}

এমনকি ল্যাম্বডা অপারেটর ব্যবহার করে আরও সুন্দর -

public class SomeState : State
{
    public override string name => "State_1";
}

উভয়ই সর্বদা "State_1" ফিরিয়ে দিত এবং অপরিবর্তনীয় থাকত।


1
এটি লিখিত হতে পারে public override string name { get; } = "State_1";যা প্রতিটি সময় মূল্য পুনরায় মূল্যায়ন করার প্রয়োজন হয় না।
ডেভ কাজিনো

2

আপনার প্রয়োজনীয়তা একটি বৈপরীত্য:

আমি স্টেটনেম নামে প্রতিটি রাজ্যের জন্য একটি স্ট্রিং সম্পত্তি তৈরি করার চেষ্টা করছি ।

বনাম

তবে আমার প্রতিটি রাজ্যে এগুলি প্রয়োগ করার দরকার নেই

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

আপনাকে হয় নিজের প্রয়োজনীয়তা পরিবর্তন করতে হবে বা সাধারণ উত্তরাধিকার ব্যতীত অন্য কিছু ব্যবহার করতে হবে।

কোড সহ একটি সম্ভাব্য সমাধান হ'ল পদ্ধতিটি Stateঅ-বিমূর্তে তৈরি করা এবং খালি স্ট্রিংটি ফিরিয়ে দেওয়া।


আমি মনে করি আপনি দ্বিতীয় বিবৃতিটি প্রসঙ্গের বাইরে রেখেছিলেন তবে আমি স্পষ্ট করে বলব। আমার গেট / সেট পদ্ধতিগুলির দরকার নেই, আমি কেবল StateName = "MyState1"প্রতিটি রাজ্যেই চাই। আমার যদি রাজ্য শ্রেণিতে এই বিবৃতি না থাকে, তবে আদর্শভাবে ভিজ্যুয়াল স্টুডিও একটি ত্রুটি তৈরি করে।
গিসমফেক্স

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

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