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 newEigenschaft, die sowohl a getals auch a setmit demselben Namen hat.
Wenn Sie nichts anderes tun, wird die alte getMethode weiterhin aufgerufen, wenn die abgeleitete Klasse über ihren Basistyp aufgerufen wird. Um dies zu beheben, fügen Sie eine abstractZwischenebene hinzu, die overridedie alte getMethode verwendet, um sie zu zwingen, getdas Ergebnis der neuen Methode zurückzugeben.
Dies ermöglicht es uns, Eigenschaften mit get/ zu überschreiben, setselbst wenn sie in ihrer Basisdefinition keine hatten.
Als Bonus können Sie bei Bedarf auch die Rückgabeart ändern.
Wenn die getBasisdefinition -only war, können Sie einen stärker abgeleiteten Rückgabetyp verwenden.
Wenn die setBasisdefinition -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 geterstellen.
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: getBestehendes 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 seteiner 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 overridedas get-nur mit get/set
Sie möchten overridemit einer get/ setEigenschaft, 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 abstractZwischenschicht
Sie können zwar nicht direkt overridemit einer get/ set-Eigenschaft arbeiten, aber Sie können :
Erstellen Sie eine new get/ set-Eigenschaft mit demselben Namen.
overridedie alte getMethode mit einem Accessor für die neue getMethode, um die Konsistenz sicherzustellen.
Also schreiben Sie zuerst die abstractZwischenschicht:
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 overridedie getEigenschaft -only verwenden. Stattdessen ersetzen Sie es durch das newSchlü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 Dals eine seiner Basisklassen angezeigt wird, z . B. Aoder 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 getwird 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 setMethoden gethinzufü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 classim Vererbungsbaum gibt. Dies kann bei Konstruktoren, die Parameter verwenden, etwas ärgerlich sein, da diese in die Zwischenebene kopiert / eingefügt werden müssen.