To jest możliwe
tl; dr - Jeśli chcesz, możesz zastąpić metodę ustawiającą tylko metodę pobierania. Po prostu:
Utwórz newwłaściwość, która ma zarówno a, jak geti a, setużywając tej samej nazwy.
Jeśli nie zrobisz nic innego, stara getmetoda będzie nadal wywoływana, gdy klasa pochodna zostanie wywołana przez jej typ podstawowy. Aby to naprawić, dodaj abstractwarstwę pośrednią, która używa overridestarej getmetody, aby zmusić ją do zwrócenia wyniku nowej getmetody.
To pozwala nam zastąpić właściwości z get/ setnawet jeśli ich brakowało w ich podstawowej definicji.
Jako bonus możesz także zmienić typ zwrotu, jeśli chcesz.
Jeśli podstawową definicją była get-only, można użyć bardziej pochodnego typu zwracanego.
Jeśli podstawową definicją było set-only, możesz użyć mniej pochodnego typu zwracanego.
Jeśli podstawową definicją była już get/ set, to:
możesz użyć bardziej pochodnego typu zwracanego, jeśliset ustawisz go -only;
możesz użyć mniej pochodnego typu zwracanego, jeśliget ustawisz go -only.
We wszystkich przypadkach możesz zachować ten sam typ zwrotu, jeśli chcesz. Poniższe przykłady używają tego samego typu zwracanego dla uproszczenia.
Sytuacja: istniejąca gettylko własność
Masz strukturę klas, której nie możesz modyfikować. Może to tylko jedna klasa lub jest to wcześniej istniejące drzewo dziedziczenia. W każdym razie chcesz dodać setmetodę do właściwości, ale nie możesz.
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: Can't overridethe- getonly with get/set
Chcesz overridez właściwością get/ set, ale nie zostanie ona skompilowana.
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
Rozwiązanie: użyj abstractwarstwy pośredniej
Chociaż nie można bezpośrednio overridez get/ setwłasności, to można :
Utwórz new get/ setproperty o tej samej nazwie.
overridestara getmetoda z akcesorium do nowej getmetody w celu zapewnienia spójności.
Więc najpierw napisz abstractwarstwę pośrednią:
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; }
}
Następnie piszesz klasę, która nie skompiluje się wcześniej. Skompiluje się tym razem, ponieważ w rzeczywistości nie jest overrideto getjedyna właściwość; zamiast tego zastępujesz go newsłowem kluczowym.
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; } }
}
Wynik: wszystko działa!
Oczywiście działa to zgodnie z przeznaczeniem 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.
Wszystko nadal działa zgodnie z przeznaczeniem, gdy jest wyświetlane Djako jedna z jego klas bazowych, np . ALub B. Ale powód, dla którego to działa, może być nieco mniej oczywisty.
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.
Jednak definicja klasy bazowej getjest nadal ostatecznie zastępowana przez definicję klasy pochodnej get, więc nadal jest całkowicie spójna.
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.
Dyskusja
Ta metoda umożliwia dodawanie setmetod gettylko do właściwości. Możesz go również używać do takich rzeczy, jak:
Zmień dowolną właściwość na get-only, set-only lub get-and- setproperty, niezależnie od tego, jaka była w klasie bazowej.
Zmień zwracany typ metody w klasach pochodnych.
Główną wadą jest to, że jest więcej do zrobienia kodowania i dodatkowy element abstract classw drzewie dziedziczenia. Może to być trochę denerwujące w przypadku konstruktorów, które przyjmują parametry, ponieważ muszą one zostać skopiowane / wklejone w warstwie pośredniej.