c# - que - Anular propiedad de solo lectura abstracta para leer/escribir propiedad
static property c# (4)
Me gustaría forzar solo la implementación de un captador de C # en una propiedad dada desde una clase abstracta base. Las clases derivadas también podrían, si lo desean, proporcionar un establecedor para esa propiedad para uso público del tipo enlazado estáticamente.
Dada la siguiente clase abstracta:
public abstract class Base
{
public abstract int Property { get; }
}
Si quiero una clase derivada que también implemente un setter, podría intentar ingenuamente:
public class Derived : Base
{
public override int Property
{
get { return field; }
set { field = value; } // Error : Nothing to override.
}
private int field;
}
Pero luego recibo un error de sintaxis ya que trato de anular el configurador no existente. Probé de alguna otra manera, como declarar privado al establecedor de bases y demás, y todavía tropiezo con todo tipo de errores que me impiden hacerlo. Debe haber una manera de hacerlo ya que no rompe ningún contrato de clase base.
De forma imprevista, se puede hacer con interfaces, pero realmente necesito esa implementación predeterminada.
Me topé con esa situación tan a menudo, me preguntaba si habría un truco de sintaxis de C # oculto para hacerlo, de lo contrario, viviré con eso e implementaré un método manual SetProperty ().
¿Esto satisfaría sus necesidades?
public abstract class TheBase
{
public int Value
{
get;
protected set;
}
}
public class TheDerived : TheBase
{
public new int Value
{
get { return base.Value; }
set { base.Value = value; }
}
}
El virtual
se eliminó, pero el valor base sigue siendo el único almacenamiento para el valor. Así que esto debería mostrar ''5''. Y el compilador debería preocuparse por b.Value = 4;
TheDerived d = new TheDerived();
d.Value = 5;
TheBase b = d;
//b.Value = 4; // uncomment for compiler error
cout << "b.Value == " << b.Value << endl;
-Jesse
¿Qué pasa con algo como:
public abstract class Base
{
public virtual int Property
{
get { return this.GetProperty(); }
set { }
}
protected abstract int GetProperty();
}
No puede hacerlo directamente, ya que no puede ser new
y override
con la misma firma en el mismo tipo; Hay dos opciones: si controlas la clase base, agrega una segunda propiedad:
public abstract class Base
{
public int Property { get { return PropertyImpl; } }
protected abstract int PropertyImpl {get;}
}
public class Derived : Base
{
public new int Property {get;set;}
protected override int PropertyImpl
{
get { return Property; }
}
}
De lo contrario, puede introducir un nivel adicional en la jerarquía de clases:
public abstract class Base
{
public abstract int Property { get; }
}
public abstract class SecondBase : Base
{
public sealed override int Property
{
get { return PropertyImpl; }
}
protected abstract int PropertyImpl { get; }
}
public class Derived : SecondBase
{
public new int Property { get; set; }
protected override int PropertyImpl
{
get { return Property; }
}
}
Tenía un requisito similar donde necesitaba una interfaz para poder compartir la funcionalidad de clasificación común entre dos clases relacionadas. Uno de ellos tenía una propiedad de orden de solo lectura y el otro tenía una propiedad de orden de lectura y escritura, pero necesitaba una forma de leer la propiedad de la misma manera en ambas clases.
Resulta que esto se puede hacer ocultando el valor de solo lectura en una interfaz derivada. Así es como lo hice.
interface ISortable
{
int Order { get; }
}
interface ISortableClass2
: ISortable
{
// This hides the read-only member of ISortable but still satisfies the contract
new int Order { get; set; }
}
class SortableClass1
: ISortable
{
private readonly int order;
public SortableClass1(int order)
{
this.order = order;
}
#region ISortable Members
public int Order
{
get { return this.order; }
}
#endregion
}
class SortableClass2
: ISortableClass2
{
#region ISortableClass2 Members
public int Order { get; set; }
#endregion
}
class RunSorting
{
public static void Run()
{
// Test SortableClass1
var list1 = new List<SortableClass1>();
list1.Add(new SortableClass1(6));
list1.Add(new SortableClass1(1));
list1.Add(new SortableClass1(5));
list1.Add(new SortableClass1(2));
list1.Add(new SortableClass1(4));
list1.Add(new SortableClass1(3));
var sorted1 = SortObjects(list1);
foreach (var item in sorted1)
{
Console.WriteLine("SortableClass1 order " + item.Order);
}
// Test SortableClass2
var list2 = new List<SortableClass2>();
list2.Add(new SortableClass2() { Order = 6 });
list2.Add(new SortableClass2() { Order = 2 });
list2.Add(new SortableClass2() { Order = 5 });
list2.Add(new SortableClass2() { Order = 1 });
list2.Add(new SortableClass2() { Order = 4 });
list2.Add(new SortableClass2() { Order = 3 });
var sorted2 = SortObjects(list2);
foreach (var item in sorted2)
{
Console.WriteLine("SortableClass2 order " + item.Order);
}
}
private static IEnumerable<T> SortObjects<T>(IList<T> objectsToSort) where T : ISortable
{
if (objectsToSort.Any(x => x.Order != 0))
{
return objectsToSort.OrderBy(x => x.Order);
}
return objectsToSort;
}
}