Providing member variables of an abstract class from a subclass

What is the โ€œrightโ€ way to provide a value in an abstract class from a particular subclass?

those. should i do this:

abstract class A { private string m_Value; protected A(string value) { m_Value = value; } public string Value { get { return m_Value; } } } class B : A { B() : this("string value") {} } 

or that:

 abstract class A { protected A() { } public abstract string Value { get; } } class B : A { B() {} public override string Value { get { return "string value"; } } } 

or something else?

And do you need to do different things if the Value property is used only in an abstract class?

+4
source share
7 answers

I usually prefer the first approach because it requires less code in the child classes.

However, I admit that the semantics of the second approach are clearer in a subtle way. Overriding a property says that "implementing this property is part of my identity." Passing a constructor argument has a different connotation: "I am setting a value in this other thing, which is simply my base class." It implies composition (has-a), not inheritance (is-a).

And you need to do different things if the Value property is used only in an abstract class?

In this case, you should definitely use the first (constructor-oriented) approach so that you can hide this implementation detail from subclasses.

Similarly, if you need to use a value in the constructor; as Mark noted , this is a real technical reason for using the first approach. Although it does not matter in this particular scenario, if someone later modifies the property override to use some other member variable in the derived class, you may have a subtle error at your fingertips.

+1
source

It depends; should the base class know about this in ctor? If so, an override approach might be a bad idea ( virtual doesn't work very well inside ctor). Otherwise, everything is in order.

+1
source

I think the second idiom is better because it is more manageable (if your base class needs several properties defined in a derived class, the constructor may become messy). It is also clear where the information goes. If you see the Value property, then you know that it is defined in a subclass. In the first example, you must track the definition point of the m_Value variable, which can be changed in the base class.

+1
source

I think this is almost the same, choose one of the methods and stick to it for consistency.

Both of your decisions force the derived class to provide value, which is good; possible alternative if value is not required:

 abstract class A { public string Value { get; protected set; } } 

My personal preference is your first option (constructor parameter), because I personally think that it is more clear, but it really is a matter of taste.

+1
source

It depends.

I use the first method if I need to change the Value in an abstract class.

I will use the second method only if I need to inherit many classes from A and somewhere, I need to put the inherited classes in a base abstract class.

If both of the above are not true, I will use the second approach, which is more manageable and clean.

If Value used only in an abstract class, I will declare it as a private field instead of a property.

+1
source

One of the main advantages of the second case is that it allows the subclass to define behavior for the Value property, which can be more complex than a simple scalar value. For example, you can calculate a value based on other fields that the subclass defines. With the first approach this is not possible, but the second approach allows this.

0
source

I prefer the second one. It allows you to specify a value without adding the actual field to the class if the value is constant or can be computed at runtime. The less state you have (fewer fields), the more supported you are likely to find the code.

0
source

All Articles