Es posible
tl; dr : puede anular un método get-only con un setter si lo desea. Básicamente es solo:
Cree una newpropiedad que tenga a gety a setusando el mismo nombre.
Si no hace nada más, getse seguirá llamando al método anterior cuando se llame a la clase derivada a través de su tipo base. Para solucionar esto, agregue una abstractcapa intermedia que use overrideen el getmétodo anterior para forzarlo a devolver el getresultado del nuevo método.
Esto nos permite anular propiedades con get/ setincluso si carecían de una en su definición base.
Como beneficio adicional, también puede cambiar el tipo de devolución si lo desea.
Si la definición base era get-solo, entonces puede usar un tipo de retorno más derivado.
Si la definición base era set-solo, entonces puede usar un tipo de retorno menos derivado.
Si la definición base ya era get/ set, entonces:
En todos los casos, puede mantener el mismo tipo de retorno si lo desea. Los siguientes ejemplos usan el mismo tipo de retorno por simplicidad.
Situación: getpropiedad preexistente solo
Tiene alguna estructura de clase que no puede modificar. Tal vez es solo una clase, o es un árbol de herencia preexistente. En cualquier caso, desea agregar un setmétodo a una propiedad, pero no puede.
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: No puede overrideel get-sólo con get/set
Desea overridecon una propiedad get/ set, pero no se compilará.
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
Solución: use una abstractcapa intermedia
Si bien no puede directamente overridecon una propiedad get/ set, puede :
Cree una propiedad new get/ setcon el mismo nombre.
overrideEl getmétodo anterior con un descriptor de acceso al nuevo getmétodo para garantizar la coherencia.
Entonces, primero escribes la abstractcapa intermedia:
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; }
}
Luego, escribe la clase que no se compilaría antes. Se va a compilar esta vez porque no estás en realidad override'ing la getpropiedad -sólo; en cambio, lo está reemplazando con la newpalabra clave.
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; } }
}
Resultado: ¡Todo funciona!
Obviamente, esto funciona según lo 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.
Todo sigue funcionando según lo previsto cuando se ve Dcomo una de sus clases base, por ejemplo, Ao B. Pero, la razón por la que funciona podría ser un poco menos obvio.
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.
Sin embargo, la definición de clase base de gettodavía está anulada en última instancia por la definición de la clase derivada de get, por lo que sigue siendo completamente coherente.
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.
Discusión
Este método le permite agregar setmétodos a solo getpropiedades. También puedes usarlo para hacer cosas como:
Cambie cualquier propiedad a una propiedad get-only, set-only o get-and- set, independientemente de lo que haya sido en una clase base.
Cambiar el tipo de retorno de un método en clases derivadas.
Los principales inconvenientes son que hay más codificación que hacer y un extra abstract classen el árbol de herencia. Esto puede ser un poco molesto con los constructores que toman parámetros porque deben copiarse / pegarse en la capa intermedia.