Frage

Ich habe eine abstrakte Basisklasse, und ich mag ein Feld oder eine Eigenschaft deklarieren, die einen anderen Wert in jeder Klasse haben, die von dieser übergeordneten Klasse erbt.

Ich will es in der Basisklasse definieren, so kann ich es in einer Basisklasse Methode Referenz - zum Beispiel ToString überschreiben zu sagen: „Dieses Objekt ist vom Typ Objekt / Feld “. Ich habe drei Möglichkeiten, die ich, dies zu tun sehen, aber ich habe mich gefragt - was ist die beste oder akzeptierte Art und Weise, dies zu tun? Newbie Frage, sorry.

Option 1:
Verwenden Sie eine abstrakte Eigenschaft und außer Kraft setzen sie auf den geerbten Klassen. Diese profitiert von durchgesetzt werden (Sie haben es außer Kraft zu setzen), und es ist sauber. Aber es fühlt sich etwas falsch ein hart Codewert zurückzukehren, anstatt ein Feld einkapseln und es ist nur ein paar Zeilen Code, anstatt nur. Ich habe auch einen Körper erklärt für „set“, aber das ist weniger wichtig (und es ist wahrscheinlich ein Weg, dies zu vermeiden, die ich bin mir nicht bewusst).

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

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

Option 2
Ich kann einen öffentlichen Bereich (oder einen geschützten Bereich) erklären und es explizit in der vererbten Klasse außer Kraft setzen. Das folgende Beispiel gibt mir eine Warnung „neu“ zu verwenden, und ich kann wohl tun, aber es fühlt sich falsch und es bricht den Polymorphismus, was der ganze Punkt war. Scheint nicht wie eine gute Idee ...

abstract class Mother
{
    public int MyInt = 0;
}

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

Option 3
Ich kann einen geschützten Bereich nutzen und den Wert im Konstruktor festgelegt. Das scheint ziemlich ordentlich, aber verlässt sich auf mich zu gewährleisten der Konstruktor immer setzt diese und mit mehreren ladenen Konstruktoren gibt es immer eine Chance, einige Codepfad den Wert nicht gesetzt.

abstract class Aunt
{
    protected int MyInt;
}

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

Es ist ein bisschen eine theoretische Frage, und ich denke, die Antwort-Option zu sein hat 1, da es das einzige ist sicher Option, aber ich bin immer nur in dem Griff C # und wollte diese Leute fragen, mit mehr Erfahrung.

War es hilfreich?

Lösung

Von den drei Lösungen nur Option 1 ist polymorphe .

Felder selbst kann nicht außer Kraft gesetzt werden. Was genau ist, warum Option 2 gibt die neue Keyword-Warnung.

Die Lösung für die Warnung ist nicht die „neue“ Schlüsselwort anhängen, sondern implementieren Option 1.

Wenn Sie Ihr Feld sein müssen polymorphen Sie es in einer Eigenschaft wickeln müssen.

Option 3 ist OK, wenn Sie nicht polymorphes Verhalten brauchen. Sie sollten jedoch daran denken, dass, wenn zur Laufzeit die Eigenschaft MyInt zugegriffen wird, die abgeleitete Klasse hat wieder keinen Einfluss auf den Wert. Die Basisklasse für sich allein ist in der Lage, diesen Wert zurückzugeben.

Dies ist, wie eine wirklich polymorphe Implementierung Ihrer Immobilie aussehen könnte, die abgeleiteten Klassen ermöglicht in seine Kontrolle .

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 */ }
    }
}

Andere Tipps

Option 2 ist ein Rohrkrepierer -. Sie können nicht Überschreibung Felder, können Sie nur verbergen sie

Ich persönlich würde gehen für Option 1 jedes Mal. Ich versuche Felder jederzeit privat zu halten. Das ist, wenn Sie wirklich überhaupt die Eigenschaft außer Kraft setzen müssen in der Lage sein, natürlich. Eine weitere Option ist eine schreibgeschützte Eigenschaft in der Basisklasse zu haben, die von einem Konstruktor Parameter gesetzt:

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)
    {
    }
}

Das ist wahrscheinlich der am besten geeignete Ansatz, wenn der Wert nicht über die gesamte Lebensdauer der Instanz ändern.

Option 2 ist eine schlechte Idee. Es wird in so genannten Schatten führen; Grundsätzlich haben Sie zwei verschiedene „MyInt“ Mitglieder, in der Mutter und die andere in der Tochter. Das Problem dabei ist, dass Methoden, die in der Mutter umgesetzt werden, werden die Mutter der „MyInt“ verweisen, während Methoden in der Tochter implementiert werden die Tochter der „MyInt“ verweisen. dies kann einige schwerwiegende Lesbarkeit Probleme verursachen und Verwirrung später auf der ganzen Linie.

Ich persönlich denke, die beste Option ist 3; denn es bietet einen klaren zentralen Wert und kann intern durch Kinder ohne lästiges definieren ihre eigenen Felder referenziert werden -., die das Problem mit der Option 1

ist

Sie könnte wie folgt definiert werden:

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

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

Durch den Wert als Nur-Lese-Einstellung sorgt dafür, dass der Wert für diese Klasse für die Lebensdauer des Objekts unverändert bleibt.

Ich nehme an, die nächste Frage ist: Warum brauchen Sie es

?

Sie können dies tun

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

virtual können Sie eine Eigenschaft einen Körper bekommen, der etwas tut und lässt noch Unterklassen es außer Kraft setzen.

Wenn Sie eine Klasse bauen, und Sie wollen es ein Grundwert für die Eigenschaft sein, dann verwenden Sie das virtual Schlüsselwort in der Basisklasse. So können Sie optional die Eigenschaft außer Kraft setzen.

Arbeiten mit dem obigen Beispiel:

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

In einem Programm:

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

würde ich mit der Option 3, gehe aber eine abstrakte setMyInt Methode, die Unterklassen gezwungen sind, zu implementieren. Auf diese Weise werden Sie nicht das Problem eines abgeleiteten Klasse Vergessen, um es im Konstruktor festgelegt.

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

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

Durch die Art und Weise, mit der Option ein, wenn Sie nicht angeben, eingestellt; in Ihrer abstrakten Basisklasse Eigenschaft, wird die abgeleitete Klasse muss es nicht umsetzen.

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

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

Sie mit der Option gehen 3, wenn Sie Ihre abstrakte Basisklasse ändern Sie den Eigenschaftswert im Konstruktor benötigen, werden Sie Wege nicht entgehen lassen. Ich würde wirklich diese Option in Betracht ziehen.

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

}

Natürlich können Sie dann immer noch die Möglichkeit, machte das Feld private und dann, je nach Bedarf, ein geschütztes oder öffentliches Eigentum Getter ausgesetzt wird.

Ich habe das ...

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

So können Sie noch Felder verwenden können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top