93

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 .

Graviton
  • 81,782
  • 146
  • 424
  • 602
  • Let's break this down a little. You need to build a set of classes that expose a method to read a `double` value which will be implemented specifically in each class. Sometimes this value will need to be set, and so some of these classes should expose a way of setting this. Is this right? How many levels of inheritance are you required to use? – Codesleuth Jan 08 '10 at 09:55
  • 1
    @Codesleuth: yes. As to how many levels of inheritance, I am not sure how this is relevant to the question? – Graviton Jan 08 '10 at 10:10
  • @David, ironically this seems like a question that I don't want to accept answer for. – Graviton Jan 29 '10 at 04:54
  • 3
    I don't understand why this is possible for interfaces but not abstract classes. What gives? – BlueRaja - Danny Pflughoeft Jul 31 '12 at 22:28
  • This is so sucky. Does anyone understand why this is not possible? get and set properties are really translated to method equivalents somewhere along the compilation road aren't they? So virtuality of these methods could be isolated matters? edit: I think maybe I found my answer here: http://stackoverflow.com/questions/82437/why-is-it-impossible-to-override-a-getter-only-property-and-add-a-setter – Mattias Nordqvist Mar 30 '16 at 18:35
  • Note that this feature has been under consideration since 2016 (see https://github.com/dotnet/roslyn/issues/9482 ). It is currently a [backlog feature](https://github.com/dotnet/roslyn/wiki/Labels-used-for-issues). – Brian Dec 19 '17 at 21:59

13 Answers13

28

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;
}
David M
  • 71,481
  • 13
  • 158
  • 186
21

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;}
}
Brian
  • 25,523
  • 18
  • 82
  • 173
  • 6
    While this is true, it's nor a good general-purpose solution to the problem. Certainly there will be many cases where a public setter is desired. – Tom Bogle Oct 09 '18 at 12:31
17

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; }
}
Laurent Etiemble
  • 27,111
  • 5
  • 56
  • 81
  • 13
    Not a bad approach; but sometimes you just need to use abstract class, not interface. – Graviton Jan 08 '10 at 09:41
  • Graviton's concern is partially mitigated by C# 8, which introduces [Default Interface Methods](https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/default-interface-methods-versions). – Brian Jan 28 '21 at 17:09
10

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.

herzmeister
  • 11,101
  • 2
  • 41
  • 51
  • 1
    OK, but what about those subclasses that don't need to set the `MyPop` ? – Graviton Jan 08 '10 at 11:19
  • Maybe they can derive only from BaseClass then and not from DClass? – herzmeister Jan 08 '10 at 11:28
  • I don't think that's a good idea for my apps; inheritance should be reserved for `is a` relationship, not to work around a language limitation; besides I make use of inheritance for other more realistic purpose in the application here. – Graviton Jan 08 '10 at 14:57
  • 1
    I actually never had problems with this issue, and I'm fanatic about OO correctness, believe me ;-) ... (although OO has limits, mind you) ... Maybe when you tell me about your exact scenario I could make a proposal about your model. – herzmeister Jan 08 '10 at 15:32
  • I think that's about it, the issue I have with using inheritance to subclass `set` operation is that I have to reserve inheritance for the real `is a` relationship – Graviton Jan 08 '10 at 15:50
  • 1
    I was thinking more about a real world example I'd like to see of what you'd want to model. For example your Animal, Giraffe and Lion classes or your CelestialBody, Meteor and Planet classes. – herzmeister Jan 09 '10 at 22:16
  • This isn't really any more helpful than just using a separate setter method. For any of the subclasses that don't really need a setter, you're adding an extra data member. The most general-purpose need here is the case of a true (public) setter, in which case you might just as well add a public setter method and use a private backing field for the subclasses that need it. – Tom Bogle Oct 09 '18 at 12:36
5

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?

mattjames
  • 1,636
  • 1
  • 12
  • 14
2

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. ;)

gotopie
  • 2,594
  • 1
  • 20
  • 23
2

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.

1

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.

Thiago Romam
  • 439
  • 4
  • 14
1

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.

Falcon08
  • 31
  • 5
0
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.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
-1

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; }
}
Codesleuth
  • 10,321
  • 8
  • 51
  • 71
-2

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.

Pondidum
  • 11,457
  • 8
  • 50
  • 69
-3

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.

Rune Grimstad
  • 35,612
  • 10
  • 61
  • 76
  • 1
    The base class is abstract and *has no implementation*, therefore `new` can't work. – Joey Jan 08 '10 at 09:28
  • To clarify: This doesn't work because of the derived class not implementing the abstract property. Above comment may have been mildly inaccurate. – Joey Jan 08 '10 at 09:36
  • My comment was misleading as well (suggested that "new" could work at all) so I removed it. Thanks for the update though. – Benjamin Podszun Jan 08 '10 at 09:38