Override get, but not set

Viewed 79772

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 .

13 Answers

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

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

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.

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?

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

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.

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

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.

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.

Related