我正在尝试创建一个使用getter定义属性的抽象类。我想将它留给派生类来决定是否要为属性实现setter。这可能吗?
到目前为止我所拥有的:
public abstract class AbstractClass {
public abstract string Value { get; }
public void DoSomething() {
Console.WriteLine(Value);
}
}
public class ConcreteClass1 : AbstractClass {
public override string Value { get; set; }
}
public class ConcreteClass2 : AbstractClass {
private string _value;
public override string Value {
get { return _value; }
}
public string Value {
set { _value = value; }
}
}
public class ConcreteClass3 : AbstractClass {
private string _value;
public override string Value {
get { return _value; }
}
public void set_Value(string value) {
_value = value;
}
}
在ConcreteClass1
中,我在set
上收到错误消息。它无法覆盖set_Value
,因为AbstractClass中不存在可覆盖的set访问器。
在ConcreteClass2
中,我在Value
上都收到错误,因为已经声明了具有相同名称的成员。
ConcreteClass3
不会出错,但即使将Value的set访问器编译为set_Value,它也无法正常工作。定义set_Value
并不意味着Value
获得设置的访问者。所以我不能为ConcreteClass3.Value属性赋值。我可以使用ConcreteClass3.set_Value(“value”),但这不是我想要在这里实现的。
是否可以让抽象类需要一个公共getter,同时允许在派生类中定义一个可选的setter?
如果你想知道,这只是一个理论问题。我没有真正的情况需要这样的事情。但我可以想象一个抽象类不关心属性如何设置,但确实需要能够获取属性。
答案 0 :(得分:33)
不幸的是,你无法做到你想要的。您可以通过接口执行此操作:
public interface IInterface {
string MyProperty { get; }
}
public class Class : IInterface {
public string MyProperty { get; set; }
}
我这样做的方法是在具体类中使用单独的SetProperty方法:
public abstract class AbstractClass {
public abstract string Value { get; }
}
public class ConcreteClass : AbstractClass {
private string m_Value;
public override string Value {
get { return m_Value; }
}
public void SetValue(string value) {
m_Value = value;
}
}
答案 1 :(得分:6)
找到解决方案:How to override a getter-only property with a setter in C#?
public abstract class A
{
public abstract int X { get; }
}
public class B : A
{
public override int X { get { return 0; } }
}
/*public class C : B //won't compile: can't override with setter
{
private int _x;
public override int X { get { return _x; } set { _x = value; } }
}*/
public abstract class C : B //abstract intermediate layer
{
public sealed override int X { get { return this.XGetter; } }
protected abstract int XGetter { get; }
}
public class D : C //does same thing, but will compile
{
private int _x;
protected sealed override int XGetter { get { return this.X; } }
public new virtual int X { get { return this._x; } set { this._x = value; } }
}
D
现在相当于一个继承自B
的类,同时也可以在setter中覆盖。
答案 2 :(得分:1)
您可以只使用protected
访问修饰符。由于继承,您不允许使用private
。看起来像这样:
public abstract class A
{
public abstract int prop { get; protected set; }
}
public abstract class B : A
{
public override int prop { get; protected set; }
}
答案 3 :(得分:0)
不是很优雅,但是如果没有像在concreteclass3中做的那样,你可以得到最接近的
public class Concrete : AbstractClass
{
public new void DoSomething()
{
Console.WriteLine(Value);
}
}
public abstract class AbstractClass
{
protected AbstractClass()
{
try
{
var value = Value;
}
catch (NotImplementedException)
{
throw new Exception("Value's getter must be overriden in base class");
}
}
public void DoSomething()
{
Console.WriteLine(Value);
}
/// <summary>
/// Must be override in subclass
/// </summary>
public string Value { get { throw new NotImplementedException(); } }
}