-1

Below I have some simple code with a Parent Class and a Child one that extends from it.

using System;

//Base Class
public class Parent {
    public void foo() {
        Console.WriteLine("Parent");
    }
}

//Child Class
public class Child : Parent
{
    new public void foo() {
        Console.WriteLine("child");
    }
}

Parent parent = new Child();
parent.foo();

I'm confused as to how the two lines above work. I would've expected the compiler to bark while trying to instantiate a Parent as its own subclass. Also, why then would 'parent.foo()' still call its Parent version.

user2402616
  • 1,434
  • 4
  • 22
  • 38
  • 1
    Why would you think that you would not able to instantiate a `Parent` object? After all, the `Parent` class is just a bog-standard, run-of-the-mill, normal, ordinary class. Just another class inheriting from `Parent` does not make `Parent` non-instantiable (also, a compiler should normally not crash. If the compiler would take issue with your source code, the compiler would emit error message, but it would not crash...) –  Jun 03 '19 at 17:12
  • My confusion is with how I could create a Parent from a 'new Child()' – user2402616 Jun 03 '19 at 17:14
  • Technically, you're instantiating a `Child` class because you're using `new Child()`. And you're declaring that new class as a `Parent`. – Toby Artisan Jun 03 '19 at 17:14
  • 2
    You are mixing method overriding with shadowing. And, you also should read a basic tutorial on OOP. I would suggest you to read the official docs at Microsoft Docs. Like this one: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/object-oriented-programming#Inheritance – Camilo Terevinto Jun 03 '19 at 17:15
  • 1
    Well, a `Child` instance is by nature also a `Parent` instance (because the `Child` class inherits from `Parent`), hence why a `Child` instance can be treated as if it were a `Parent` instance (including assigning a `Child` instance to a variable of type `Parent` / having a reference/variable of type `Parent` referring to a `Child` instance). With regard to the method call: you are not overriding the method in child, but you are rather doing what is called "member/method hiding" (also called "member shadowing", see Camilo's comment before mine) –  Jun 03 '19 at 17:16
  • 1
    Since `Child` extends `Parent`, you can say that `Child` is a `Parent`. When a class inherits/extends another class, then it can be declared as the class that it inherits/extends. Because it is declared as a `Parent`, you will only be able to use the methods that are on the `Parent`, even though the runtime instantiated the class as a `Child` class. – Toby Artisan Jun 03 '19 at 17:18
  • 2
    With regard to member hiding/shadowing, you might want to read here: https://stackoverflow.com/questions/3838553/overriding-vs-method-hiding (Also, generally stay away from using member hiding. Haphazardly using member hiding without really understanding what it does will lead to bugs and unexpected behavior in your program) –  Jun 03 '19 at 17:20

2 Answers2

1

At first you shouldn't hide base class method by using new keyword you should just override it by derived class method by using virtual and override keywords. It will also fix issue that method was called from base class not from derived.

For details how it works you should read about inheritance in C#.

When you hiding method by using new keyword it always using implementation of method that is in your declared type, in your case it Parent. But if you use virtual and override it using implementation of method that is in initialized type, in your case it Child.

using System;

public class Parent 
{
    public virtual void foo() 
    {
        Console.WriteLine("Parent");
    }
}

public class Child : Parent
{
    public override void foo() 
    {
        Console.WriteLine("Child");
    }
}
Lemm
  • 196
  • 1
  • 9
0

why then would 'parent.foo()' still call its Parent version?

Because you are shadowing foo by using new.

Virtual or abstract methods can be overridden by subclasses:

//Base Class
public class Parent
{
    public virtual void foo()
    {
        Console.WriteLine("Parent");
    }
}

//Child Class
public class Child : Parent
{
    public override void foo()
    {
        Console.WriteLine("child");
    }
}

I would read all of the documentation linked in the comments to decide whch will work best for your use case.

Parrish Husband
  • 3,148
  • 18
  • 40