P.Brian.Mackey
P.Brian.Mackey

Reputation: 44275

Why does this sometimes mean base?

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

Answers (5)

Sean U
Sean U

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 overrides 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

Steven Doggart
Steven Doggart

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

user703016
user703016

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

Tigran
Tigran

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

Phillip Schmidt
Phillip Schmidt

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

Related Questions