To jest możliwe
tl; dr - Jeśli chcesz, możesz zastąpić metodę ustawiającą tylko metodę pobierania. Po prostu:
Utwórz new
właściwość, która ma zarówno a, jak get
i a, set
używając tej samej nazwy.
Jeśli nie zrobisz nic innego, stara get
metoda będzie nadal wywoływana, gdy klasa pochodna zostanie wywołana przez jej typ podstawowy. Aby to naprawić, dodaj abstract
warstwę pośrednią, która używa override
starej get
metody, aby zmusić ją do zwrócenia wyniku nowej get
metody.
To pozwala nam zastąpić właściwości z get
/ set
nawet 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 get
tylko 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ć set
metodę 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 override
the- get
only with get
/set
Chcesz override
z 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 abstract
warstwy pośredniej
Chociaż nie można bezpośrednio override
z get
/ set
własności, to można :
Utwórz new
get
/ set
property o tej samej nazwie.
override
stara get
metoda z akcesorium do nowej get
metody w celu zapewnienia spójności.
Więc najpierw napisz abstract
warstwę 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 override
to get
jedyna właściwość; zamiast tego zastępujesz go new
sł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 D
jako jedna z jego klas bazowych, np . A
Lub 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 get
jest 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 set
metod get
tylko 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- set
property, 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 class
w 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.