Abstract property with public getter, define private setter in concrete class possible?

72,085

Solution 1

Unfortunately, you can't do exactly what you want. You can do this with interfaces though:

public interface IInterface {
    string MyProperty { get; }
}

public class Class : IInterface {
    public string MyProperty { get; set; }
}

The way I would do it is to have a separate SetProperty method in the concrete classes:

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;
    }
}

Solution 2

Found a solution: 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 is now equivalent to a class inheriting from B while also being able to override in a setter.

Solution 3

You can just use protected access modifier instead. Because of inheritance you are not allowed to use private. It looks like so:

public abstract class A
{
    public abstract int prop { get; protected set; }
}

public abstract class B : A
{
    public override int prop { get; protected set; }
}
Share:
72,085
comecme
Author by

comecme

Updated on September 09, 2020

Comments

  • comecme
    comecme over 3 years

    I'm trying to create an abstract class that defines a property with a getter. I want to leave it up to derived classes to decide if they want to implement a setter for the property or not. Is this possible?

    What I have so far:

    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;
        }
    }
    

    In ConcreteClass1, I get an error on the set. It can't override set_Value because no overridable set accessor exists in AbstractClass.

    In ConcreteClass2, I get an error on both Value's because a member with the same name is already declared.

    ConcreteClass3 doesn't give an error, but even though Value's set accessor would be compiled into set_Value, it doesn't work the other way around. Defining a set_Value does not mean that Value gets a set accessor. So I can't assign a value to a ConcreteClass3.Value property. I can use ConcreteClass3.set_Value("value"), but that's not what I'm trying to achieve here.

    Is it possible to have the abstract class demand a public getter, while allowing an optional setter to be defined in a derived class?

    In case you'r wondering, this is just a theoretical question. I don't have a real situation where something like this is needed. But I can imagine an abstract class that doesn't care how a property gets set, but that does need to be able to get the property.