সাবক্লাসে ওভাররাইডিং ক্ষেত্র বা বৈশিষ্ট্যগুলি


145

আমার একটি বিমূর্ত বেস শ্রেণি আছে এবং আমি এই ক্ষেত্র বা এমন একটি সম্পত্তি ঘোষণা করতে চাই যে এই প্যারেন্ট বর্গ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত প্রতিটি শ্রেণিতে আলাদা আলাদা মান থাকবে।

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

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

abstract class Father
{
    abstract public int MyInt { get; set;}
}

class Son : Father
{
    public override int MyInt
    {
        get { return 1; }
        set { }
    }
}

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

abstract class Mother
{
    public int MyInt = 0;
}

class Daughter : Mother
{
    public int MyInt = 1;
}

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

abstract class Aunt
{
    protected int MyInt;
}

class Niece : Aunt
{
    public Niece()
    {
        MyInt = 1;
    }
}

এটি কিছুটা তাত্ত্বিক প্রশ্ন এবং আমি অনুমান করি যে উত্তরটি বিকল্প 1 হবে কারণ এটি একমাত্র নিরাপদ বিকল্প তবে আমি কেবল সি # এর সাথে আঁকড়ে ধরছি এবং আরও অভিজ্ঞতার সাথে এই ব্যক্তিদের জিজ্ঞাসা করতে চেয়েছিলাম।


বিমূর্ত পাবলিক INT MyInt {get; সেট;} => পাবলিক বিমূর্ত স্ট্রিং ইনটেন্টনেম {get; সেট;}: ডি
নাভিদ গোলফৌশন

উত্তর:


136

তিনটি সমাধানের মধ্যে কেবল অপশন 1 হ'ল বহুমুখী

নিজের দ্বারা ক্ষেত্রগুলি ওভাররাইড করা যায় না। ঠিক এই কারণেই বিকল্প 2 নতুন কীওয়ার্ড সতর্কতা ফেরত দেয় ।

সতর্কতার সমাধানটি হল "নতুন" কীওয়ার্ড সংযোজন নয়, বিকল্প 1 প্রয়োগ করা।

যদি আপনার ক্ষেত্রটি বহুমুখী হতে হয় তবে আপনাকে এটি কোনও সম্পত্তিতে আবৃত করতে হবে।

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

উদ্ভূত শ্রেণিগুলিকে নিয়ন্ত্রণে রাখার ফলে আপনার সম্পত্তিটির সত্যিকারের বহুতল বাস্তবায়ন দেখতে পাওয়া যেতে পারে ।

abstract class Parent
{
    abstract public int MyInt { get; }
}

class Father : Parent
{
    public override int MyInt
    {
        get { /* Apply formula "X" and return a value */ }
    }
}

class Mother : Parent
{
    public override int MyInt
    {
        get { /* Apply formula "Y" and return a value */ }
    }
}

153
একদিকে যেমন, আমি সত্যিই মনে করি বাবার উচিত "Y", এবং মাতৃকুলভাবে, "এক্স" সূত্রটি প্রয়োগ করা উচিত।
পিটার - মনিকা পুনরায়

4
আমি যদি প্যারেন্টে একটি ডিফল্ট বাস্তবায়ন সরবরাহ করতে চাই এবং এটি বিমূর্ত না হয়?
অ্যারন ফ্র্যাঙ্ক

@ অ্যারোনফ্রেঙ্ক স্বাক্ষর করুন: পাবলিক ভার্চুয়াল ইন মাইআইএন্ট {পান; }
টেড বিঘাম


18

বিকল্প 2 একটি অ-স্টার্টার - আপনি ক্ষেত্রগুলিকে ওভাররাইড করতে পারবেন না , আপনি কেবল সেগুলি আড়াল করতে পারেন ।

ব্যক্তিগতভাবে, আমি প্রতিবার 1 বিকল্পে যাব। আমি ক্ষেত্রটি সর্বদা ব্যক্তিগত রাখার চেষ্টা করি। অবশ্যই যদি আপনার অবশ্যই সম্পত্তিটি মোটেই ওভাররাইড করতে সক্ষম হওয়া দরকার। অন্য বিকল্পটি হ'ল বেস ক্লাসে কেবল পঠনযোগ্য সম্পত্তি থাকতে হবে যা কনস্ট্রাক্টর প্যারামিটার থেকে সেট করা থাকে:

abstract class Mother
{
    private readonly int myInt;
    public int MyInt { get { return myInt; } }

    protected Mother(int myInt)
    {
        this.myInt = myInt;
    }
}

class Daughter : Mother
{
    public Daughter() : base(1)
    {
    }
}

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


আমরা এখন এই সঠিক নয় এই উপর ভিত্তি করে বলতে পারি msdn.microsoft.com/en-us/library/9fkccyh4.aspx MSDN নিবন্ধ শো আপনি বৈশিষ্ট্য ওভাররাইড করতে পারে
codingbiz

1
@ কোডিংবিজ: আমার উত্তর কোথায় সম্পত্তি সম্পর্কে কথা বলবে? ক্ষেত্র এবং বৈশিষ্ট্যগুলি একই জিনিস নয়।
জন স্কিটি

@ কোডিংবিজ: (আমার উত্তর এখন সম্পত্তি সম্পর্কে কথা বলেছে, স্বীকারোক্তি দিয়ে - তবে এটি কখনও বলেনি যে আপনি সেগুলি ওভাররাইড করতে পারবেন না। এটি বলেছে - এবং বলেছে - আপনি ক্ষেত্রগুলিকে ওভাররাইড করতে পারবেন না , যা এখনও সঠিক))
জোন স্কিট

7

বিকল্প 2 একটি খারাপ ধারণা। এর ফলে ছায়া নামানো কিছু ঘটবে; মূলত আপনার দুটি ভিন্ন "মাইআইন্ট" সদস্য রয়েছে, একজন মায়ের মধ্যে এবং অন্যটি কন্যায়। এটির সাথে সমস্যাটি হ'ল মায়ের ক্ষেত্রে যে পদ্ধতিগুলি প্রয়োগ করা হয় সেগুলি মায়ের "মাইআইন্ট" উল্লেখ করবে এবং কন্যায় প্রয়োগকৃত পদ্ধতিগুলি মেয়ের "মাইআইন্ট" উল্লেখ করবে। এটি কিছু গুরুতর পাঠযোগ্যতার সমস্যা সৃষ্টি করতে পারে এবং পরে লাইনটিতে বিভ্রান্তি সৃষ্টি করতে পারে।

ব্যক্তিগতভাবে, আমি মনে করি সেরা বিকল্পটি 3; কারণ এটি একটি স্পষ্ট কেন্দ্রীভূত মান সরবরাহ করে এবং বাচ্চারা তাদের নিজস্ব ক্ষেত্রগুলি সংজ্ঞায়িত করার ঝামেলা ছাড়াই অভ্যন্তরীণভাবে রেফারেন্স করতে পারে - যা বিকল্প 1 এর সমস্যা।


6

আপনি এটি করতে পারে

class x
{
    private int _myInt;
    public virtual int myInt { get { return _myInt; } set { _myInt = value; } }
}

class y : x
{
    private int _myYInt;
    public override int myInt { get { return _myYInt; } set { _myYInt = value; } }
}

ভার্চুয়াল আপনাকে এমন একটি সম্পত্তি পেতে দেয় যা কিছু করে এবং এখনও সাব-ক্লাসিকে এটিকে ওভাররাইড করতে দেয়।


4

আপনি এর মতো কিছু সংজ্ঞায়িত করতে পারেন:

abstract class Father
{
    //Do you need it public?
    protected readonly int MyInt;
}

class Son : Father
{
    public Son()
    {
        MyInt = 1;
    }
}

পাঠ্য হিসাবে মান সেট করে, এটি নিশ্চিত করে যে class শ্রেণীর মানটি বস্তুর আজীবন অপরিবর্তিত থাকবে।

আমি মনে করি পরের প্রশ্নটি: আপনার এটির প্রয়োজন কেন?


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

3

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

উপরে আপনার উদাহরণ ব্যবহার করে:

//you may want to also use interfaces.
interface IFather
{
    int MyInt { get; set; }
}


public class Father : IFather
{
    //defaulting the value of this property to 1
    private int myInt = 1;

    public virtual int MyInt
    {
        get { return myInt; }
        set { myInt = value; }
    }
}

public class Son : Father
{
    public override int MyInt
    {
        get {

            //demonstrating that you can access base.properties
            //this will return 1 from the base class
            int baseInt = base.MyInt;

            //add 1 and return new value
            return baseInt + 1;
        }
        set
        {
            //sets the value of the property
            base.MyInt = value;
        }
    }
}

একটি প্রোগ্রামে:

Son son = new Son();
//son.MyInt will equal 2

0

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

abstract class Base 
{
 protected int myInt;
 protected abstract void setMyInt();
}

class Derived : Base 
{
 override protected void setMyInt()
 {
   myInt = 3;
 }
}

যাইহোক, বিকল্প বিকল্প সহ, আপনি যদি সেটটি নির্দিষ্ট না করেন; আপনার বিমূর্ত বেস শ্রেণীর সম্পত্তিতে, উত্পন্ন শ্রেণিকে এটি প্রয়োগ করতে হবে না।

abstract class Father
{
    abstract public int MyInt { get; }
}

class Son : Father
{
    public override int MyInt
    {
        get { return 1; }
    }
}

0

আপনি 3 বিকল্পের সাথে যেতে পারেন যদি আপনি কনস্ট্রাক্টরের সম্পত্তির মান প্রয়োজন জন্য আপনার বিমূর্ত বেস শ্রেণিটি পরিবর্তন করেন তবে আপনি কোনও পথ মিস করবেন না। আমি সত্যিই এই বিকল্প বিবেচনা করব।

abstract class Aunt
{
    protected int MyInt;
    protected Aunt(int myInt)
    {
        MyInt = myInt;
    }

}

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


0

আমি এটা করেছি...

namespace Core.Text.Menus
{
    public abstract class AbstractBaseClass
    {
        public string SELECT_MODEL;
        public string BROWSE_RECORDS;
        public string SETUP;
    }
}

namespace Core.Text.Menus
{
    public class English : AbstractBaseClass
    {
        public English()
        {
            base.SELECT_MODEL = "Select Model";
            base.BROWSE_RECORDS = "Browse Measurements";
            base.SETUP = "Setup Instrument";
        }
    }
}

এইভাবে আপনি এখনও ক্ষেত্র ব্যবহার করতে পারেন।


প্রোটোটাইপিং বা ডেমোমিংয়ের জন্য এটি অ্যাড-হক সমাধান হিসাবে দুর্দান্ত বলে মনে হচ্ছে।
জিমানো

0

আপনি যখন বাস্তবায়ন সহ একটি বিমূর্ত শ্রেণি করতে চান উদাহরণ প্রয়োগকরণ। সাবক্লাস অবশ্যই:

  1. একটি বিমূর্ত শ্রেণীর প্রয়োগের প্যারামিটারাইজ করুন।
  2. বিমূর্ত শ্রেণির প্রয়োগের পুরোপুরি উত্তরাধিকারী;
  3. আপনার নিজস্ব বাস্তবায়ন আছে।

এই ক্ষেত্রে, বাস্তবায়নের জন্য প্রয়োজনীয় সম্পত্তিগুলি বিমূর্ত শ্রেণি এবং তার নিজস্ব সাবক্লাস ব্যতীত ব্যবহারের জন্য উপলব্ধ হওয়া উচিত নয়।

    internal abstract class AbstractClass
    {
        //Properties for parameterization from concrete class
        protected abstract string Param1 { get; }
        protected abstract string Param2 { get; }

        //Internal fields need for manage state of object
        private string var1;
        private string var2;

        internal AbstractClass(string _var1, string _var2)
        {
            this.var1 = _var1;
            this.var2 = _var2;
        }

        internal void CalcResult()
        {
            //The result calculation uses Param1, Param2, var1, var2;
        }
    }

    internal class ConcreteClassFirst : AbstractClass
    {
        private string param1;
        private string param2;
        protected override string Param1 { get { return param1; } }
        protected override string Param2 { get { return param2; } }

        public ConcreteClassFirst(string _var1, string _var2) : base(_var1, _var2) { }

        internal void CalcParams()
        {
            //The calculation param1 and param2
        }
    }

    internal class ConcreteClassSecond : AbstractClass
    {
        private string param1;
        private string param2;

        protected override string Param1 { get { return param1; } }

        protected override string Param2 { get { return param2; } }

        public ConcreteClassSecond(string _var1, string _var2) : base(_var1, _var2) { }

        internal void CalcParams()
        {
            //The calculation param1 and param2
        }
    }

    static void Main(string[] args)
    {
        string var1_1 = "val1_1";
        string var1_2 = "val1_2";

        ConcreteClassFirst concreteClassFirst = new ConcreteClassFirst(var1_1, var1_2);
        concreteClassFirst.CalcParams();
        concreteClassFirst.CalcResult();

        string var2_1 = "val2_1";
        string var2_2 = "val2_2";

        ConcreteClassSecond concreteClassSecond = new ConcreteClassSecond(var2_1, var2_2);
        concreteClassSecond.CalcParams();
        concreteClassSecond.CalcResult();

        //Param1 and Param2 are not visible in main method
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.