new - オーバーライド メリット c#




サブクラスのフィールドまたはプロパティをオーバーライドする (6)

抽象基本クラスがあり、この親クラスから継承する各クラスに異なる値を持つフィールドまたはプロパティを宣言する必要があります。

私はベースクラスでそれを定義したいので、ベースクラスのメソッドで参照することができます。たとえば、ToStringをオーバーライドして "This object is type / field "とすることができます。 私はこれを行うことがわかる3つの方法がありますが、これを実行するには最高の、あるいは受け入れられる方法は何ですか? 初心者の質問、申し訳ありません。

オプション1:
抽象プロパティを使用し、継承されたクラスでそれをオーバーライドします。 これは強制される(あなたがそれを上書きしなければならない)ことから利益を得、それはきれいです。 しかし、フィールドをカプセル化するのではなく、ハードコードの値を返すのはやや間違っているように感じます。 私はまた、 "セット"のボディを宣言する必要がありますが、あまり重要ではありません(そして、私が気づいていないものを避ける方法がおそらくあります)。

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

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

オプション2
私はパブリックフィールド(または保護されたフィールド)を宣言し、継承されたクラスで明示的にオーバーライドすることができます。 以下の例は私に "new"を使用する警告を与え、私はおそらくそれを行うことができますが、それは間違っていると感じて、それは全体の点である多型を破ります。 良いアイデアのようには思われません...

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でなければならないと思いますが、私はちょうどC#を把握しており、より多くの経験を持つ人々のこれを尋ねたかった。


3つのソリューションのうち、 オプション1のみが多態性です。

フィールド自体はオーバーライドできません。 これは、 オプション2新しいキーワード警告を返す理由です。

警告の解決策は、「新しい」キーワードを追加するのではなく、オプション1を実装することです。

あなたのフィールドがポリモーフィックである必要がある場合は、それをプロパティにラップする必要があります。

多態性の動作が必要ない場合、 オプション3はOKです。 ただし、実行時にプロパティ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 */ }
    }
}

あなたはこれを行うことができます

class x
{
    private int _myInt;
    internal 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; } }
}

virtualを使うと、何かをしてサブクラスがそれをオーバーライドできるようにすることができます。


これは私がしました...

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";
        }
    }
}

このようにしてもフィールドを使用できます。


オプション2は悪い考えです。 シャドーイングと呼ばれるものが発生します。 基本的に、あなたは2つの異なる "MyInt"メンバーを持っています。一つは母親に、もうひとつは娘にあります。 この問題は、母親に実装されているメソッドが母親の "MyInt"を参照する一方、娘に実装されたメソッドは娘の "MyInt"を参照することになります。 これはいくつかの重大な可読性の問題を引き起こす可能性があり、後で混乱することがあります。

個人的には、最良の選択肢は3だと思います。 それは明確な中央値を提供し、オプション1の問題である、自分のフィールドを定義するという面倒なことなしに、子どもが内部的に参照することができるからです。


クラスを構築していてプロパティのベース値が必要な場合は、ベースクラスの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

抽象基底クラスを変更してコンストラクタ内のプロパティ値を要求すると、オプション3を使用することができます。パスを見逃すことはありません。 私は本当にこのオプションを考えています。

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

}

もちろん、フィールドを非公開にし、必要に応じて保護されたプロパティゲッターまたは公開プロパティゲッターを公開するオプションもあります。





field