Reputation: 1349
I'm trying to teach myself about OOP in C#, but I have a question about when to use base
. I understand the general principles, but I'm not sure what's best in the example below. This simple test includes:
interface
with two string
propertiesabstract
class that implements this interface and adds a couple more string
propertiesbase
and the other doesn't, but they both produce the same output when the program is executed.My question is: in this example, is one implementation more desirable than the other? I'm not really sure if there are any meaningful differences between TranslationStyleA
and TranslationStyleB
, or if it's just down to personal preference?
Many thanks for your time and thoughts!
using System;
namespace Test
{
interface ITranslation
{
string English { get; set; }
string French { get; set; }
}
public abstract class Translation : ITranslation
{
public virtual string English { get; set; }
public virtual string French { get; set; }
public string EnglishToFrench { get { return English + " is " + French + " in French"; } }
public string FrenchToEnglish { get { return French + " is " + English + " in English"; } }
public Translation(string e, string f)
{
English = e;
French = f;
}
}
public class TranslationStyleA : Translation
{
public override string English
{
get { return base.English; }
set { base.English = value; }
}
public override string French
{
get { return base.French; }
set { base.French = value; }
}
public TranslationStyleA(string e, string f) : base(e, f)
{
}
}
public class TranslationStyleB : Translation
{
private string english;
public override string English
{
get { return english; }
set { english = value; }
}
private string french;
public override string French
{
get { return french; }
set { french = value; }
}
public TranslationStyleB(string e, string f) : base(e, f)
{
this.English = e;
this.French = f;
}
}
class Program
{
static void Main(string[] args)
{
TranslationStyleA a = new TranslationStyleA("cheese", "fromage");
Console.WriteLine("Test A:");
Console.WriteLine(a.EnglishToFrench);
Console.WriteLine(a.FrenchToEnglish);
TranslationStyleB b = new TranslationStyleB("cheese", "fromage");
Console.WriteLine("Test B:");
Console.WriteLine(b.EnglishToFrench);
Console.WriteLine(b.FrenchToEnglish);
Console.ReadKey();
}
}
}
Upvotes: 3
Views: 318
Reputation: 56467
You don't really need to override any of the superclass properties to achieve the effect that you intend, since you don't enhance the superclass behavior in any way.
If you remove the abstract
modifier from the base Translation
, you don't need the subclasses anymore, since it will be functionally equivalent to both.
Now, as to when to use base
; you should use it when you want to access functionality in the superclass that's been overridden in the subclass. base
calls are always statically bound to the superclass method at compile time; even if the superclass method is virtual
(as in your case). For a curious thing that can happen with base
calls take a look here.
Upvotes: 3
Reputation: 13419
As mentioned before, style A reuses the fields already declared whereas style B declares new fields. Regarding your question about when to use base, the rule of thumb would be "whenever you would like to reuse logic/code defined in the parent class".
Upvotes: 2
Reputation: 8882
It does come down to how you intend to leverage your constructs.
As implemented, the overridden members on TranslationStyleA are a bit redundant as the consumer could just as easily access the base members without providing the overrides in the base derivation. In cases such as these I personally won't bother overriding the base members at all if doing so doesn't add any value to design.
The second implementation is common when you truly want to override the setting and accessing of base class members, for instance, if the setting of a base class member is the catalyst for initiating another operation then the overriden member on the derivation would be an appropriate place for that to occur.
Upvotes: 1
Reputation: 51329
The first thing that you need to understand is what's going on when you have an automatic property:
public virtual string English { get; set; }
Behind the scenes, the compiler is generating a private field, and getting/setting that private field when you access the property. It is equivalent to this
private string _english;
public virtual string English { get { return _english; } set { _english = value; } }
except that you don't know the name of the private field, and so you cannot access it.
So in your TranslationStyleA
class, you are not actually doing anything with the English property, because it just accesses the base class's property directly and doesn't change it's behavior.
// None of this is even needed- we are just delegating to the base class
public override string English
{
get { return base.English; }
set { base.English = value; }
}
Now in the TranslationStyleB
class, you are actually changing the behavior of the property (albeit in a fairly useless way). Instead of storing the value for the English property in the base class's auto-implemented private variable, you are storing it in the private variable defined at the derived class level:
private string english;
public override string English
{
get { return english; }
set { english = value; }
}
Neither of these implementations does anything of course, and as implemented neither is needed, since the base class implements the properties perfectly fine itself. So my answer to your original question is that neither is preferred, given the code as you describe it.
Now, let's look at an example where your question is relevant. You only need to override them if you want to change their behavior, for instance.
// We don't want any leading or trailing whitespace, so we remove it here.
public override string English
{
get { return base.English; }
set { base.English = value.Trim(); }
}
We want to delegate to the base class here, because of why these were properties in the first place. Semantically, a property is the same as a field:
public String Foo;
public String Foo { get; set; } // <-- why bother with all this extra { get; set; } stuff?
The reason is that from the compiler's perspective, it is a breaking change in an interface to go from a property to a field. So if I change
public String Foo;
to
public String Foo { get; set; }
Then any code that depends on my code needs to be recompiled. However, if I change
public String Foo { get; set; }
to
private string _foo;
public String Foo { get { return _foo; } set { _foo = value.Trim(); } }
then dependent code still only sees the public property, and does not need recompilation (because the interface of my class has not changed).
If the base class here (Translation
) were to change it's behavior for the property English
thus:
private string _english;
public String English { get { return _english; } set { _english = value.ToUpper(); } }
the you would want to pick that up in your derived classes!
So considering that properties have behavior associated with them, you should always delegate to the parent class implementation unless that implementation has undesirable effects in your deriving class.
Upvotes: 5
Reputation: 129011
The first style is definitely preferable unless you have some good reason to pick the other one.
The automatically-implemented properties of Translation
each add a field, and style B adds more rather than using the ones the compiler added. Style A reuses the one the compiler added, saving some storage.
Additionally, there's no need to override the superclass's properties if you're not going to change their functionality. You could even write another style like this:
public class TranslationStyleC : Translation {
public TranslationStyleC(string e, string f) : base(e, f) {
}
}
Upvotes: 4