Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading methods in inherited classes

Tags:

c#

.net

clr

I have started to understand that I do not understand what is going on. There is the following behavior in C#:

public class Base
{
    public void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }
}

public class Derived: Base
{
    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }
}

public class B { }

public class D: B { }

class Program
{
    static void Main(string[] args)
    {
        Derived derived = new Derived();
        D d = new D();

        derived.Method(d);
    }
}

It will print

public void Method(B a)

instead of

public void Method(D a)

It's surprising. I suppose that the reason of this behavior is implementation of methods table. CLR does not search methods in the base class if it finds the corresponding method in the current type. I think they were trying to improve performance.

But I was completely disappointed with the following code:

public class Base
{
    public virtual void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }
}

public class Derived: Base
{
    public override void Method(D a)
    {
        Console.WriteLine("public override void Method(D a)");
    }

    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }

}

public class B { }

public class D: B { }

class Program
{
    static void Main(string[] args)
    {
        Derived derived = new Derived();
        D d = new D();

        derived.Method(d);
    }
}

and it will print

public void Method(B a)

instead of

public override void Method(D a)

It's awful and very unpredictable.

Can anyone explain it?

I suppose that the method table has methods that have been implemented in the current type only (excluding overriding methods) and CLR stops looking for the corresponding method as soon as any method that can be called is found. Am I right?

like image 603
Yaroslav Avatar asked Jan 31 '17 21:01

Yaroslav


People also ask

Can you overload inherited methods?

Note: In a subclass, you can overload the methods inherited from the superclass. Such overloaded methods neither hide nor override the superclass instance methods—they are new methods, unique to the subclass.

What is overloading in inheritance?

Overloading allows several function definitions for the same name, distinguished primarily through different argument types; it is typically resolved at compile-time. Inheritance allows subclasses to define more special versions of the same function; it is typically resolved at run-time.

Is method overloading possible in child class?

That means methods can be overridden only in child classes. Constructors and private methods are not inherited, so they cannot be overridden. Abstract methods must be overridden by the first concrete (non-abstract) subclass. final methods cannot be overridden.

Which inheritance and overloading is not possible in Java?

Java doesn't support multiple inheritance.


2 Answers

I have started to understand that I do not understand what is going on.

Thus begins wisdom.

It's awful and very unpredictable.

It is neither. By contrast, the feature is designed to reduce unpredictability by eliminating a cause of the brittle base class failure.

Can anyone explain it?

See my 2007 article on the subject.

https://blogs.msdn.microsoft.com/ericlippert/2007/09/04/future-breaking-changes-part-three/

The short version though is: a method in a derived class is always better than a method in a base class; the person who wrote the derived class knows more about the object semantics and is handling a more specific case than the person who wrote the base class.

Servy points out that I did not cover your second point. Why does the override in the derived class not make the "D" method "in the derived class"?

Virtual methods are considered to be methods of the class where they were declared, not of the class where they were most recently overridden. Why? Because choosing to override or not is an implementation detail of a class, and not part of the public surface area.

I mean, think about it. You write some code, it works, and then you say, hey, I'm going to make a new (or remove an old!) override of this method somewhere in this type hierarchy, and suddenly that changes overload resolution somewhere else? That is exactly the sort of brittleness that C# seeks to eliminate.

Remember, C# was very carefully designed for a world in which code is being edited by teams of people. Many modern languages were, bizarrely, designed as though one person was writing all the code and they got it right the first time; that's not realistic. Some of the more unusual features of C#, like the one you've discovered, are there to help you keep your program behaviour predictable even as other people are editing your base classes.

like image 121
Eric Lippert Avatar answered Sep 21 '22 15:09

Eric Lippert


I can see the confusion here. Eric's answer could be better illustrated with an example. If you changed the code as follows...

public class Base
{
    public virtual void Method(D a)
    {
        Console.WriteLine("public void Method(D a)");
    }

    public void Method(B a)
    {
        Console.WriteLine("public void Method(B a)");
    }
}

public class Derived : Base
{
    public override void Method(D a)
    {
        Console.WriteLine("public override void Method(D a)");
    }

}

public class B { }

public class D : B { }

The output becomes "public override void Method(D a)".

Why?

As stated in Eric's article...

methods in a base class are not candidates if any method in a derived class is applicable

As both Method(D) and Method(B) are now in the base class, Method(D) has become the closest match which is overrided in your derived class hence the output.

Pretty confusing for a newbie hey? Well pretty confusing for an experienced developer also. I think the key point to make here is that what you have here is bad design, I'm not talking about the CLR or C# compiler, it's done the best it can do to help you out here, I'm talking about the classes in your example.

I think a common mistake made by many people new to OOP is to overuse the new toy that is inheritance. Inheritance is often not the favoured relationship used in OOD. When you start studying OOP design patterns you'll note that many of the patterns do not use inheritance.

Why? Because your example illustrates the sort of confusion that can be created when using inheritance, it is known as Fragile Inheritance. Design patterns more often use aggregation and composition to divide up a problem space into a more workable, extensible and manageable solution.

Inheritance is a powerful construct, as with most powerful things, it should be used sparingly and with care.

like image 39
Mick Avatar answered Sep 21 '22 15:09

Mick