具有公共getter的抽象属性,可以在具体类中定义私有setter吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有公共getter的抽象属性,可以在具体类中定义私有setter吗?相关的知识,希望对你有一定的参考价值。

我正在尝试创建一个使用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?

如果你想知道,这只是一个理论问题。我没有真正的情况需要这样的事情。但我可以想象一个抽象类,它不关心如何设置属性,但确实需要能够获取属性。

答案

不幸的是,你无法做到你想要的。您可以使用接口执行此操作:

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;
    }
}
另一答案

找到了解决方案: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中覆盖。

另一答案

不是很优雅,但它是你在没有像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(); } }
}

以上是关于具有公共getter的抽象属性,可以在具体类中定义私有setter吗?的主要内容,如果未能解决你的问题,请参考以下文章

您可以强制从抽象基类继承的类仅具有在基本情况下定义的公共方法吗?

JAVA中接口与抽象类

如果wen可以定义公共属性,Angular2为啥要使用getter

014 接口和抽象类有什么区别?

具体类中的受保护构造函数与抽象类中的公共构造函数

该属性必须是有效的实体类型,并且该属性应该具有非抽象的 getter 和 setter。实体框架 [重复]