In the following example I am able to create a virtual method Show()
in the inherited class and then override it in the inheriting class.
I want to do the same thing with the protected class variable prefix
but I get the error:
The modifier 'virtual' is not valid for this item
But since I can't define this variable as virtual/override in my classes, I get the compiler warning:
TestOverride234355.SecondaryTransaction.prefix' hides inherited member 'TestOverride234355.Transaction.prefix'. Use the new keyword if hiding was intended.
Luckily when I add the new
keyword everything works fine, which is ok since I get the same functionality, but this raises two questions:
Why I can use virtual/override for methods but not for protected class variables?
What is the difference actually between the virtual/override approach and the hide-it-with-new approach since at least in this example they offer the same functionality?
Code:
using System;
namespace TestOverride234355
{
public class Program
{
static void Main(string[] args)
{
Transaction st1 = new Transaction { Name = "name1", State = "state1" };
SecondaryTransaction st2 =
new SecondaryTransaction { Name = "name1", State = "state1" };
Console.WriteLine(st1.Show());
Console.WriteLine(st2.Show());
Console.ReadLine();
}
}
public class Transaction
{
public string Name { get; set; }
public string State { get; set; }
protected string prefix = "Primary";
public virtual string Show()
{
return String.Format("{0}: {1}, {2}", prefix, Name, State);
}
}
public class SecondaryTransaction : Transaction
{
protected new string prefix = "Secondary";
public override string Show()
{
return String.Format("{0}: {1}, {2}", prefix, Name, State);
}
}
}
Rather create a property for the prefix member - this way you can set the property to virtual/abstract
Fields are used to store state for an object, they help the object encapsulate data and hide implementation concerns from others. By being able to override a field we are leaking the implementation concerns of the class to client code (including subtypes). Due to this most languages have taken the decision that one cannot define instance variables that can be overridden (although they can be public/protected... so you can access them).
You also cannot put instance variables in an interface
Overriding a field does not really make sense. It's part of the state of the base class, and if an inheriting class wishes to change it, it should be changable in the inheriting class by giving it an appropriate visibility.
One thing you could do in your case is to set
prefix
in the constructor for the inheriting class:You can also make a property instead of a field, and make the property virtual. This will enable you to change the behavior of the getter and setter for the property in the inheriting class:
EDIT: As for your question of using a variable in a base constructor before an inheriting class has set it, one way to solve this is to define an initialization method in the base class, override it in the inheriting class, and call it from the base constructor before accessing any fields:
EDIT 2: You also asked what the difference between virtual/override and name hiding (the new keyword on methods) is, if it should be avoided, and if it can be useful.
Name hiding is a feature that breaks inheritance in the case of hiding virtual methods. I.e., if you hide the
Initialize()
method in the child class, the base class will not see it, and not call it. Also, if theInitialize()
method was public, external code that was callingInitialize()
on a reference of the base type would be callingInitialize()
on the base type.Name hiding is useful when a method is non-virtual in a base class, and a child wants to provide a different implementation of its own. Note, however, that this is NOT the same as virtual/override. References of the base type will call the base type implementation, and references of the child type will call the child type implementation.
You can't because there is no use. What would you accomplish by overriding a field? Simple:
This will print 8 9 instead of 9 9 as expected. I need a base class functional, but I also need a inherited class with I could manipulate (increase) the vars inside internal group classes vars. Its not possible!!
You can't because there is no use. What would you accomplish by overriding a field?
In your example, if you didn't override "Show" in the SecondaryTransaction class, then calling Show on an instance of SecondaryTransaction would actually be calling the method in the base class (Transaction), which would therefore use "Show" in the base class, resulting in output of:
So, depending on what method you were calling (i.e. one on the base class or the child class), the code would have a different value for "prefix" which would be a maintainability nightmare. I suspect what you probably want to/should do, is expose a property on Transaction that wraps "prefix".
You can't override a field because it's an implementation detail of the base class. You can change the value of a protected field, but by overriding it you'd essentially be saying I want to replace the field, not the value.
What I would do (if I absolutely didn't want to/couldn't use properties) :
Edit: (As per my comment on another answer)
If you're calling down into your base class's ctor and need the value set, then you'll probably have to modify Transaction, possibly like this:
Overriding a field is a nonsense. Marking field as protected you automatically may access them in derived classes. You may override functions, properties, because it uses functions internally.