Override get, but not set

C#

C# Problem Overview


I have an abstract class that defines a get, but not set, because as far as that abstract class is concerned, it needs only a get.

public abstract BaseClass
{
  public abstract double MyPop
  {get;}
}

However, in some of the derive class, I need a set property, so I am looking at this implementation

public class DClass: BaseClass
{
  public override double MyPop
  {get;set;}
}

The problem is, I got a compilation error, saying that

> *.set: cannot override because *. does not have an overridable set accessor.

Even though I think that the above syntax is perfectly legitimate.

Any idea on this? Workaround, or why this is so?

Edit: The only approach I can think of is to put both get and set as in the abstract class, and let the subclass throws a NotImplementedException if set is called and it's not necessary. That's something I don't like, along with a special setter method .

C# Solutions


Solution 1 - C#

One possible answer would be to override the getter, and then to implement a separate setter method. If you don't want the property setter to be defined in the base, you don't have many other options.

public override double MyPop
{
    get { return _myPop; }
}

public void SetMyPop(double value)
{
    _myPop = value;
}

Solution 2 - C#

New in C# 6.0:

If you are only calling the setter within your constructor, you can resolve this problem using read-only properties.

void Main()
{
	BaseClass demo = new DClass(3.6);
}

public abstract class BaseClass
{
	public abstract double MyPop{ get; }
}

public class DClass : BaseClass
{
	public override double MyPop { get; }
	public DClass(double myPop) { MyPop = myPop;}
}

Solution 3 - C#

It is not possible to do what you want. You have to define the setter in the abstract property, otherwise you won't be able to override it properly.

The only case I know where a getter is defined and a getter/setter are implemented is by using an interface:

public interface IBaseInterface
{
    double MyPop { get; }
}

public class DClass : IBaseInterface
{
    public double MyPop { get; set; }
}

Solution 4 - C#

If BaseClass is in your own codebase, then you can do:

abstract public class BaseClass
{
    abstract public double MyPop { get; protected set; }
}

public class DClass : BaseClass
{
    private double _myProp;
    public override double MyProp
    {
        get { return _myProp; }
        protected set { _myProp = value; }
    }
}

EDIT: You can then go make a public method in DClass SetMyProp(double myProp) or the like. The class design for your domain model should be clear about or speak for itself why you can't set the property directly in the base class and why you can do so in the derived one.

Solution 5 - C#

Are you sure that doing what you are trying to do would be a good design if you found a way to do it?

It would allow objects of the subclass to make state changes that objects of the parent class can not make. Wouldn't that violate the Liskov Substitution Principle?

Solution 6 - C#

You could do something like this:

abstract class TestBase { public abstract int Int { get; } }

class TestDerivedHelper : TestBase
{
    private int _Int;
    public override int Int
    {
        get
        {
            return _Int;
        }
    }

    protected void SetInt(int value)
    {
        this._Int = value;
    }
}

class TestDerived : TestDerivedHelper
{
    public new int Int
    {
        get { return base.Int; }
        set { base.SetInt(value); }
    }
}

Using TestDerived will have the functionality you're looking for. The only drawback I can see from this method is that you have to implement every abstract method in TestDerivedHelper, but it gives you more control later.

Hope this helps. ;)

Solution 7 - C#

The reason that this is not possible is due to the way parameters are "Magicked" into existence by C#. When you define a parameter, C# creates a private field that the implicit getter and setter manipulate. If there is no setter in the base class, it's impossible to change this variable from a method written in a sub class (as the private flag prohibits even sub classes from accessing it). What usually happens is it uses the implicit setter of the base class instead.

I wouldn't advise putting the set in the base class if not all sub classes can do it, because this goes against the whole principle of polymorphic programming (any abstract method defined in the abstract class must be implemented by a subclass). Creating a special setter method, as described in other answers is probably the best way go.

Solution 8 - C#

Siege

abstract class TestBase
{
    public abstract int Int { get; }
}

class TestDerivedHelper : TestBase
{
    private int _Int;
    public override int Int
    {
        get
        {
            return _Int;
        }
    }

    protected void SetInt(int value)
    {
        this._Int = value;
    }
}

class TestDerived : TestDerivedHelper
{
    public new int Int
    {
        get { return base.Int; }
        set { base.SetInt(value); }
    }
}

> Using TestDerived will have the functionality you're looking for. The > only drawback I can see from this method is that you have to implement > every abstract method in TestDerivedHelper, but it gives you more > control later.

I use this approach and works very well for me. Also, I made my "TestDerivedHelper" class abstract too, then all the methods must be implemented on "TestDerived" class.

Solution 9 - C#

Even though this thread is old I'm positing my solution, in case it helps someone. It is not my own but is based off answers in other SO topics.

public abstract BaseClass
{
  public double MyPoP { get { return GetMyPoP; } }

  protected abstract double GetMyPoP { get; }
}

public class DClass: BaseClass
{
  public new double MyPoP { get; set; }

  protected override double GetMyPop { get { return MyPoP; } }
}

This solution adds an extra line of code for each such property that needs accessor modified. However, there is no change to external visibility and provides needed functionality.

Solution 10 - C#

public abstract class BaseClass
{
    public abstract double MyPop { get; }
}

public class DClass: BaseClass
{
    private double _myPop = 0;
    public override double MyPop 
    {
        get { return _myPop; }
    }

    // some other methods here that use the _myPop field
}

If you need to set the property from outside DClass then maybe it would be better to put the setter into the base class.

Solution 11 - C#

EDIT:

OK I may have been hasty with this response, but I've given it some more thought now.

Do you have to use an abstract base class? If it's not required, try this:

public interface ISomeRelevantName
{
	double MyPop { get; }
}

public class DClass : ISomeRelevantName
{
	public double MyPop { get; set; }
}

Solution 12 - C#

Why not just have a property in the base class that has a private setter, then in your subclass that needs the setter, override it and make it public.

Solution 13 - C#

You cannot override the set accessor since the base class has no set accessor defined.

What you can do is use the new keyword to hide the base classes implementation, but that may not be what you want.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGravitonView Question on Stackoverflow
Solution 1 - C#David MView Answer on Stackoverflow
Solution 2 - C#BrianView Answer on Stackoverflow
Solution 3 - C#Laurent EtiembleView Answer on Stackoverflow
Solution 4 - C#herzmeisterView Answer on Stackoverflow
Solution 5 - C#mattjamesView Answer on Stackoverflow
Solution 6 - C#gotopieView Answer on Stackoverflow
Solution 7 - C#andrew monteithView Answer on Stackoverflow
Solution 8 - C#Thiago RomamView Answer on Stackoverflow
Solution 9 - C#Falcon08View Answer on Stackoverflow
Solution 10 - C#Darin DimitrovView Answer on Stackoverflow
Solution 11 - C#CodesleuthView Answer on Stackoverflow
Solution 12 - C#PondidumView Answer on Stackoverflow
Solution 13 - C#Rune GrimstadView Answer on Stackoverflow