Kamran Ahmed
Kamran Ahmed

Reputation: 12440

C# Inheritance and Overriding of functions

class Parent
{
    public void foo() 
    {
        Console.WriteLine("Hello from the foo inside Parent");
    }

    public virtual void bar() 
    {
        Console.WriteLine("Hello from the bar inside Parent.");
    }

    public void foobar() 
    {
        Console.WriteLine("Hello from the foobar inside Parent.");
    }
}
class Child : Parent
{
    public void foo()
    {
        base.foo();
        Console.WriteLine("Hello from the foo inside Child");
    }        

    public override void bar() 
    {
        base.bar();
        Console.WriteLine("Hello from the bar inside Child.");
    }

    public new void foobar() 
    {
        base.foobar();
        Console.WriteLine("Hello from the foobar inside Child.");            
    }
}

Above is the code that I was using to test my knowlege of inheritance in C# but I have a confusion here:

  1. Function foo() inside the child hides the foo() of parent.
  2. Function bar() inside the child hides the bar() of parent.
  3. Function foobar() inside the child hides the bar() of parent()

All the three functions use different techniques for hiding the parent function. Can anyone please guide me, What's the different between these three and which one to use when?

Upvotes: 3

Views: 1447

Answers (3)

Pharap
Pharap

Reputation: 4082

Firstly, 1 and 3 are the same, the compiler/IDE (Visual Studio) automatically assumes you meant to do number 3 if you do number 1. You will notice that it puts a green line under the name foo() and tells you to use the new keyword. So in reality, there are only two types of inheritance-based method altering:

  1. Method overriding
  2. Method hiding

Method overriding is when a class declares its method to be virtual, which essentially says 'any class that inherits from me is free to override this'. It means that no matter what, if the child class overrides that method, the overridden version is called.

Method hiding, on the other hand, is the child being rebellious and saying 'as long as I exist as a child class, I am going to ignore my parent implementation and do this instead'. The trick here is that the moment the child class is being treated like its parent, the parent's implementation gets called instead.

Here is an example, assuming your class set-up is being used:

Child c = new Child();
c.foo();
c.bar();
Parent p = c;
p.foo();
p.bar();

Note that the Child c can be stored in a parent variable because of its inheritance. Any child class that inherits from a parent class can be treated as an instance of its parent.

Now try adding this class into the mix:

class MaleChild : Parent
{
    public new void foo()
    {
        base.foo();
        Console.WriteLine("Hello from the foo inside MaleChild");
    }

    public override void bar()
    {
        base.bar();
        Console.WriteLine("Hello from the bar inside MaleChild.");
    }
}

And running a similar test:

Parent[] p = new Parent[2];

p[0] = new Child();
p[1] = new MaleChild();

p[0].foo();
p[0].bar();
p[1].foo();
p[1].bar();

Now you see that even though two inherited classes are both being treated as their parent, the overridden methods are unique to the inherited class. This allows the parent class to define a basic outline for how it works, whilst child classes refine this and do things more specifically. And yet because the child class can do everything the parent can, it can be treated as a parent.

This concept is known as polymorphism.

Upvotes: 3

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236308

To see difference try following code:

Console.WriteLine("Parent->Parent");
Parent p = new Parent();
p.foo();
p.bar();
p.foobar();

In this case you have variable of type Parent which points to instance of Parent class. Nothing is hidden or overridden here. Methods of parent class are called. Now create variable of Child type, which points to instance of Child:

Console.WriteLine("Child->Child");
Child c = new Child();
c.foo();
c.bar();
c.foobar();

In this case all methods of child class are invoked. Also nothing interesting. Now create variable of Parent type, which points to instance of Child:

Console.WriteLine("Parent->Child");
Parent p = new Child();
p.foo(); // you have warning and parent method is invoked
p.bar(); // child overridden method invoked
p.foobar(); // no warning, parent method is invoked

In this case you can see polymorphism in action - methods, which are overridden in child class are invoked. If method is not overridden, then parent's method is invoked. But you will have one warning message:

Warning 1 'Namespace.Child.foo()' hides inherited member 'Namespace.Parent.foo()'. Use the new keyword if hiding was intended.

It says that, you have declared in child class method with same signature as method in parent class, which hides parent class implementation. Hiding is different from overriding, as you can see from last sample. When you have variable of parent type, then members overridden in child will be called. But hidden method are not called in last case.

Normally you don't need such behavior (i.e. hiding some members), this is why compiler warns you. But if for some reason you need this behavior (e.g. you don't own parent class code and can't make parent's method virtual) then you should use new keyword to suppress this warning and show that you understand what you are doing. That's why you don't see warning for foobar method.

Upvotes: 2

tafa
tafa

Reputation: 7326

First of all, the first and third one are the same, only difference is the third one will not give a compile time warning

Child.foo()' hides inherited member `Parent.foo()'. Use the new keyword if hiding was intended

The real value of inheritance shows up when you have a variable of base type and don't know the type of the instance the variable is pointing to.

Please examine the output of the first three calls and how they differ from the last three calls.

Parent p = new Child();
Child c = new Child();

p.foo();
p.bar();
p.foobar();
Console.WriteLine("------------------------");
c.foo();
c.bar();
c.foobar();

Upvotes: 1

Related Questions