In a lot of languages, you can override the value of a property of a class when extending an abstract class, and the parent methods will read this new variable when used, an example would be something like this:
abstract class A {
protected string foo;
void PrintFoo() {
print(foo);
}
}
class B extends A {
protected string foo = "bar";
}
(new B()).PrintFoo();Â //Â outputs: bar
In C# I haven’t been able to find a standard way to do this, as this is not allowed.
One way I’ve found is by passing it by parent constructor like:
abstract class A {
protected string foo;
public A(string foo) {
this.foo = foo;
}
void PrintFoo() {
Console.WriteLine(foo);
}
}
class B : A {
public B() : A("bar") {}
}
(new B()).PrintFoo();Â //Â outputs: bar
But clearly this is not clean at all.
Another way I’ve seen is by making a virtual string and overriding it later (which would be similar to the other languages):
abstract class A {
protected virtual string Foo { get; }
void PrintFoo() {
Console.WriteLine(Foo);
}
}
class B : A {
protected override string Foo {
get { return "bar"; }
}
}
(new B()).PrintFoo();Â //Â outputs: bar
It seems as to me the second way is the appropriate one, but it’s not as clean as I expected.
Is there a better way?
>Solution :
You can’t override a field, only methods (and properties and the like). In order to change a fields default-value, you can assign it in the derived class’ constructor:
class B : A
{
public B() { foo = "bar"; } // you have access to foo, as it's protected field
}
You should however make your field readonly, to avoid changing it after your instance was created.
Apart from this what you consider "not clean at all" is a really good solution, in my opinion, as it enables you to limit the access to the field even further to private:
class A
{
private string foo;
public A(string f) { this.foo = f; }
}
class B : A
{
public B : A("bar") { }
}
This way not even B can access or manipulate the fields value. However it’s pretty up to you if you need this kind of security.
Another way would be to wrap the field in a property and override that one:
class A
{
public virtual string Foo => null;
}
class B : A
{
public override string Foo => "bar";
}
I’d not say this is per-se better, as properties aren’t per-se better than fields. If it were that simple, public or prtoteced fields probably were forbidden by the compiler (shouldn’t be that hard to implement that). However exposing fields to the outside of your class makes it hard to keep track on when they change. That’s whay people love properties, as they encapsulate the field to keep track on its changes. It’s easy to validate the new value for a property. Doing that on a field can become a nighmare soon.