Reputation: 44275
Given
public class Animal
{
public Animal()
{
Console.WriteLine("Animal constructor called");
}
public virtual void Speak()
{
Console.WriteLine("animal speaks");
}
}
public class Dog: Animal
{
public Dog()
{
Console.WriteLine("Dog constructor called");
this.Speak();
}
public override void Speak()
{
Console.WriteLine("dog speaks");
base.Speak();
}
}
this.Speak()
calls Dog.Speak()
. Remove Speak()
from dog and suddenly this.Speak()
calls Animal.Speak()
. Why does this
behave this way? In other words, why does this
mean base
or this
?
To me, an explicit call to base.Speak()
makes more sense. Especially when speak is not virtual, surprisingly Speak() is still called when virtual
is removed. I understand IS-A relationships from an OO sense, but I can't wrap my head around this specific problem in C#. This gets especially annoying when people write God class UI's (practically every business does). I'm looking for "Speak()" inside "this" when I should be looking at "base".
Upvotes: 3
Views: 141
Reputation: 6850
Subclases automatically inherit behavior from their base classes. If you don't do anything other than inherit Dog
from Animal
then this.Speak()
and base.Speak()
both reference the version of Speak()
that was implemented in Animal
.
Where special things start happening is if Dog
overrides Speak()
. This is not possible unless Speak()
is virtual
. (The virtual
keyword doesn't control inheritance, it controlls overriding.)
Only when Dog
overrides Speak()
does base.Speak()
do something special: In that case, calling Speak()
(or this.Speak()
) will execute Dog
's implementation, because it override
s Animal
's implementation. This is where base
becomes useful: it allows you to get around this behavior by specifying that you want to execute the base class's implementation rather than the override.
A common use of this style is in constructors. For example:
public class Animal
{
private readonly string _name;
public Animal() : this("Animal") { }
protected Animal(string name) { _name = name; }
public void Speak() { Console.WriteLine(_name + " speaks"); }
}
public class NamedAnimal : Animal
{
public NamedAnimal(name) : base(name) { }
}
// usage:
(new Animal()).Speak(); // prints "Animal speaks"
(new NamedAnimal("Dog")).Speak(); // prints "Dog speaks"
In this example, NamedAnimal
doesn't have access to the _name
field, but it is still able to set it indirectly by calling the base class's constructor. But the base class's signature is the same as one in the base class, so it has to be specified using base
.
With non-constructors it's also useful to get at behavior that's not otherwise accessible. For example, if Animal.Speak
were virtual then we could use an override to tack behavior onto it rather than simply replacing it:
public class NamedAnimal : Animal
{
public NamedAnimal(name) : base(name) { }
public override Speak()
{
Console.Write("The animal named ");
base.Speak();
}
}
// usage:
(new NamedAnimal("Dog")).Speak(); // Writes "The animal named Dog speaks"
Upvotes: 3
Reputation: 43743
VB.Net has the MyClass
keyword to do just that (as opposed to the My
keyword, which is the equivalent of this
in C#). Unfortunately, there is no MyClass
equivalent keyword in C#.
Upvotes: 0
Reputation: 37945
This is one of the very fundamental points of OO. If you don't provide an override, then the parent method is used.
Also, even if you remove virtual
, Dog.Speak
is called because you're not accessing this
polymorphically.
Upvotes: 2
Reputation: 62246
this
means this
and nothing else.
Just in your first example you have an override for Speak(..)
function, so this
call that one.
In second case, istead, there is no any override, so it "climbs" on derivation tree and pick the first suitable function. In your case that one is Speak(..)
of the Animal
.
Upvotes: 1
Reputation: 8818
Its not that. Its that if there is a speak method within dog
, then it is an override
of the base method. If it isn't there, then calling dogInstance.Speak will look for the Speak() method in any of Dog's base classes.
Upvotes: 3