Es ist möglich
tl; dr - Sie können eine Get-Only-Methode mit einem Setter überschreiben, wenn Sie möchten. Es ist im Grunde nur:
Erstellen Sie eine new
Eigenschaft, die sowohl a get
als auch a set
mit demselben Namen hat.
Wenn Sie nichts anderes tun, wird die alte get
Methode weiterhin aufgerufen, wenn die abgeleitete Klasse über ihren Basistyp aufgerufen wird. Um dies zu beheben, fügen Sie eine abstract
Zwischenebene hinzu, die override
die alte get
Methode verwendet, um sie zu zwingen, get
das Ergebnis der neuen Methode zurückzugeben.
Dies ermöglicht es uns, Eigenschaften mit get
/ zu überschreiben, set
selbst wenn sie in ihrer Basisdefinition keine hatten.
Als Bonus können Sie bei Bedarf auch die Rückgabeart ändern.
Wenn die get
Basisdefinition -only war, können Sie einen stärker abgeleiteten Rückgabetyp verwenden.
Wenn die set
Basisdefinition -only war, können Sie uns einen weniger abgeleiteten Rückgabetyp geben.
Wenn die Basisdefinition bereits get
/ war set
, dann:
Sie können einen abgeleiteten Rückgabetyp verwenden, wenn Sie ihn nur set
-on machen.
Sie können einen weniger abgeleiteten Rückgabetyp verwenden, wenn Sie nur diesen get
erstellen.
In allen Fällen können Sie den gleichen Rückgabetyp beibehalten, wenn Sie möchten. Die folgenden Beispiele verwenden der Einfachheit halber denselben Rückgabetyp.
Situation: get
Bestehendes Eigentum
Sie haben eine Klassenstruktur, die Sie nicht ändern können. Vielleicht ist es nur eine Klasse oder es ist ein bereits vorhandener Vererbungsbaum. In jedem Fall möchten Sie set
einer Eigenschaft eine Methode hinzufügen , können dies jedoch nicht.
public abstract class A // Pre-existing class; can't modify
{
public abstract int X { get; } // You want a setter, but can't add it.
}
public class B : A // Pre-existing class; can't modify
{
public override int X { get { return 0; } }
}
Problem: Kann nicht override
das get
-nur mit get
/set
Sie möchten override
mit einer get
/ set
Eigenschaft, aber es wird nicht kompiliert.
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
Lösung: Verwenden Sie eine abstract
Zwischenschicht
Sie können zwar nicht direkt override
mit einer get
/ set
-Eigenschaft arbeiten, aber Sie können :
Erstellen Sie eine new
get
/ set
-Eigenschaft mit demselben Namen.
override
die alte get
Methode mit einem Accessor für die neue get
Methode, um die Konsistenz sicherzustellen.
Also schreiben Sie zuerst die abstract
Zwischenschicht:
public abstract class C : B
{
// Seal off the old getter. From now on, its only job
// is to alias the new getter in the base classes.
public sealed override int X { get { return this.XGetter; } }
protected abstract int XGetter { get; }
}
Dann schreiben Sie die Klasse, die nicht früher kompiliert werden würde. Diesmal wird es kompiliert, da Sie nicht override
die get
Eigenschaft -only verwenden. Stattdessen ersetzen Sie es durch das new
Schlüsselwort.
public class D : C
{
private int _x;
public new virtual int X { get { return this._x; } set { this._x = value; } }
// Ensure base classes (A,B,C) use the new get method.
protected sealed override int XGetter { get { return this.X; } }
}
Ergebnis: Alles funktioniert!
Offensichtlich funktioniert dies wie vorgesehen D
.
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
test.X = 7;
Print(test.X); // Prints "7", as intended.
Alles funktioniert immer noch wie beabsichtigt, wenn es D
als eine seiner Basisklassen angezeigt wird, z . B. A
oder B
. Der Grund, warum es funktioniert, ist jedoch möglicherweise weniger offensichtlich.
var test = new D() as B;
//test.X = 7; // This won't compile, because test looks like a B,
// and B still doesn't provide a visible setter.
Die Definition der Basisklasse von get
wird jedoch letztendlich immer noch von der Definition der abgeleiteten Klasse überschrieben get
, sodass sie immer noch vollständig konsistent ist.
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
var baseTest = test as A;
Print(test.X); // Prints "7", as intended.
Diskussion
Mit dieser Methode können Sie -only-Eigenschaften set
Methoden get
hinzufügen. Sie können es auch verwenden, um Dinge zu tun wie:
Ändern Sie jede Eigenschaft in eine get
-only-, set
-only- oder get
-and- -Eigenschaft set
, unabhängig davon, was sie in einer Basisklasse war.
Ändern Sie den Rückgabetyp einer Methode in abgeleiteten Klassen.
Die Hauptnachteile sind, dass es mehr Codierung und ein zusätzliches abstract class
im Vererbungsbaum gibt. Dies kann bei Konstruktoren, die Parameter verwenden, etwas ärgerlich sein, da diese in die Zwischenebene kopiert / eingefügt werden müssen.