views:

282

answers:

5

In a base class I have this property:

public virtual string Text 
{
    get { return text; }
}

I want to override that and return a different text, but I would also like to be able to set the text, so I did this:

public override string Text
{
    get { return differentText; }
    set { differentText = value; }
}

This however does not work. I get a red squiggly under set saying that I can not override because it does not have a set accessor. Why is this aproblem? What should I do?

+4  A: 
public virtual string Text 
{
    get { return text; }
    protected set {}
}

change base class property like this, you are trying to override set method that doesn't exist

ArsenMkrt
+3  A: 

In your second block of code you are creating a public set method, but the word "override" in the declaration makes the compiler look for a method with the same signature in the base class. Since it can't find that method it will not allow you create your set.

As ArsenMkrt says you could change your base declaration to contain a protected set. This will allow you to override it, but since you still won't be able to change the signature you can't promote this method to public in your subclass, so the code you posted still won't work.

Instead you either need to add a public virtual set method to your base class that doesn't do anything (or even throws an exception if you try and call it) but this goes against what a user of the class would expect the behaviour to be so if you do this (and I won't recommend it) make sure it is so well documented that the user can't miss it:

///<summary>
///Get the Text value of the object
///NOTE: Setting the value is not supported by this class but may be supported by child classes
///</summary>
public virtual string Text 
{
    get { return text; }
    set { }
}

//using the class

BaseClass.Text = "Wibble";
if (BaseClass.Text == "Wibble")
{
    //Won't get here (unless the default value is "Wibble")
}

Otherwise declare the set as a separate method in your child class:

public override string Text
{
    get { return differentText; }
}

public void SetText(string value)
{
    differentText = value;
}
Martin Harris
I don't like it, but I guess I will have to do something along the lines of having a separate SetText method or something... thanks :)
Svish
Well, it could also be an architectural issue. Why can't the user set the text value in the base class? Is it *really* the same property in both classes? It seems to be an usual requirement to need a pattern like this.
Martin Harris
Well, it is a number of different Parameter classes which holds different kinds of values. And I would like them all to be able to represent themselves as a text value that the user can read (for printing for example). But I don't want all the parameters to be set by text (parsing is a lot more annoying than printing). For example a date parameter I want to print the date, but I don't need to set the date through text, since the setting will be done with a datepicker.
Svish
Could be bad design of course, but I'm working on it :p
Svish
+2  A: 

It's a problem because you are breaking the encapsulation. You can't override something and make it more accessible, that would throw everything about encapsualtion out the window.

That's the rule and it applies in your case also, eventhough you are actually exposing something that is not the original value.

There is no way to do exactly what you attempted. You have to either make a setter in the base class, or use a different method of setting the new value.

Guffa
A: 

You could hide the property from the base class :

public new string Text
{
    get { return differentText; }
    set { differentText = value; }
}

But in that case that property will only be used when manipulating the object through a variable of this type, not the base type

Thomas Levesque
+2  A: 

You want more capabilities to be exposed when using a child type. It sounds like you don't want to override, you want to shadow. Just use the new keyword to hide the readonly Text property under your readable/writable property.

In base class:

protected string text;
public string Text 
{
    get { return text; }
}

In derived class:

new public string Text 
{
    get { return text; }
    set { text = value; }
}
Strilanc
Can you shadow and override at the same time?
Svish
No, they mean different things. Whether you shadow or override determines whether the behavior of Text is affected even after casting to the base type. Check out this question for a better explanation: http://stackoverflow.com/questions/673779/what-is-shadowing
Strilanc