È possibile
tl; dr - Se lo desideri, puoi sovrascrivere un metodo get-only con un setter. Fondamentalmente è solo:
Creare una newproprietà con sia a getche a setusando lo stesso nome.
Se non fai altro, il vecchio getmetodo verrà comunque chiamato quando la classe derivata viene chiamata attraverso il suo tipo base. Per risolvere questo problema, aggiungi un abstractlivello intermedio che utilizza overrideil vecchio getmetodo per forzarlo a restituire il getrisultato del nuovo metodo.
Questo ci consente di sovrascrivere le proprietà con get/ setanche se ne mancava una nella loro definizione di base.
Come bonus, puoi anche cambiare il tipo di ritorno, se lo desideri.
Se la definizione di base era get-solo, è possibile utilizzare un tipo restituito più derivato.
Se la definizione di base era set-solo, puoi usarci un tipo di ritorno meno derivato.
Se la definizione di base era già get/ set, quindi:
In tutti i casi, è possibile mantenere lo stesso tipo di restituzione, se lo si desidera. Gli esempi seguenti utilizzano lo stesso tipo restituito per semplicità.
Situazione: getproprietà solo esistente
Hai una struttura di classe che non puoi modificare. Forse è solo una classe o è un albero ereditario preesistente. In ogni caso, si desidera aggiungere un setmetodo a una proprietà, ma non è possibile.
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; } }
}
Problema: Impossibile overrideil get-Solo con get/set
Si desidera overridecon una proprietà get/ set, ma non verrà compilata.
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
Soluzione: utilizzare uno abstractstrato intermedio
Anche se non puoi direttamente overridecon una proprietà get/ set, puoi :
Crea una proprietà new get/ setcon lo stesso nome.
overrideil vecchio getmetodo con un accessor al nuovo getmetodo per garantire coerenza.
Quindi, prima scrivi il abstractlivello intermedio:
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; }
}
Quindi scrivi la classe che non si sarebbe compilata prima. Sarà compilazione questa volta perché si sta in realtà non override'ing l' getimmobile -Solo; invece, lo stai sostituendo usando la newparola chiave.
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; } }
}
Risultato: tutto funziona!
Ovviamente, questo funziona come previsto 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.
Tutto funziona come previsto quando viene visualizzato Dcome una delle sue classi di base, ad esempio Ao B. Ma il motivo per cui funziona potrebbe essere un po 'meno ovvio.
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.
Tuttavia, la definizione della classe base di getè ancora alla fine sostituita dalla definizione della classe derivata di get, quindi è ancora completamente coerente.
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.
Discussione
Questo metodo consente di aggiungere setmetodi alle getsole proprietà. Puoi anche usarlo per fare cose come:
Cambia qualsiasi proprietà in una get-only, set-only o get-and- setproprietà, indipendentemente da ciò che era in una classe base.
Modifica il tipo restituito di un metodo nelle classi derivate.
Gli svantaggi principali sono che c'è più codice da fare e un extra abstract classnella struttura ereditaria. Questo può essere un po 'fastidioso con i costruttori che accettano parametri perché devono essere copiati / incollati nel livello intermedio.