Java overloading and inheritance rules
The behavior of these method calls is dictated and described by the Java Language Specification (reference section 8.4.9).
When a method is invoked (§15.12), the number of actual arguments (and
any explicit type arguments) and the compile-time types of the
arguments are used, at compile time, to determine the signature of the
method that will be invoked (§15.12.2). If the method that is to be
invoked is an instance method, the actual method to be invoked will be
determined at run time, using dynamic method lookup (§15.12.4).
In your example, the Java compiler determines the closest match on the compile type of the instance you are invoking your method on. In this case:
A.method(AX)
The closest method is from type A, with signature A.method(A)
. At runtime, dynamic dispatch is performed on the actual type of A (which is an instance of AX), and hence this is the method that is actually called:
AX.method(A)
Is method overloading from different classes possible without inheritance? Many sources claim no. But I don't get any error. Why is that so?
Overloading a method in Java is always within a class, not from different classes
You won't get any error as is allowed what you have done
Method overloading and inheritance
Basically, the way method invocation works in C# is that the compiler looks at the most derived class first, and sees whether any newly declared methods (not including overrides) are applicable for the arguments for the call. If there's at least one applicable method, overload resolution works out which is the best one. If there isn't, it tries the base class, and so on.
I agree this is surprising - it's an attempt to counter the "brittle base class" issue, but I would personally prefer that any overridden methods were included in the candidate set.
Method invocation is described in section 7.6.5.1 of the C# 5 specification. The relevant parts here is:
- The set of candidate methods is reduced to contain only methods from the most derived types: For each method
C.F
in the set, whereC
is the type in which the methodF
is declared, all methods declared in a base type ofC
are removed from the set. Furthermore, ifC
is a class type other than object, all methods declared in an interface type are removed from the set. (This latter rule only has affect when the method group was the result of a member lookup on a type parameter having an effective base class other than object and a non-empty effective interface set.)
And in the member lookup part of 7.4, override
methods are explicitly removed:
Members that include an
override
modifier are excluded from the set.
C# method overload with inheritance
If you want to have really dynamic resolution, then you have to use dynamic
keyword, like so:
static void Main(string[] args)
{
dynamic ship = new SpaceShip();
Planet planet = new Planet();
ship.Visit(planet); // => Specific
// also
GenericPlanet genericPlanet = new GenericPlanet();
ship.Visit(planet); // Generic
}
In this case behaviour will be something like you have described - type of the parameter matters. But what you most likely want is to have a method override, like so:
class GenericSpaceShip
{
public virtual void Visit(GenericPlanet planet)
{
Console.WriteLine("Generic");
}
}
class SpaceShip : GenericSpaceShip
{
public override void Visit(GenericPlanet planet)
{
Console.WriteLine("Specific");
}
}
In this case the Specific method will be called if you have an instance of SpaceShip
and Generic method for instance of GenericSpaceShip
, regardless of planet type. In this case type of the ship matters:
static void Main(string[] args)
{
SpaceShip ship = new SpaceShip();
Planet planet = new Planet();
ship.Visit(planet); // => Specific
// also
GenericPlanet genericPlanet = new GenericPlanet();
ship.Visit(planet); // Specific
}
You would always get Generic
if GenericSpaceShip
was used instead.
Method overloading & inheritance - how to address to the right method?
Overload Resolution happens at compile time. The C# compiler uses the static type of an argument to find the best overload. Since you are calling the method with an argument of type Child
, the compiler does not find a matching overload. None of the three overloads has a parameter of type Child
. There is no implicit conversion from Child
to BoyChild
, GirlChild
or UndecidedChild
. You can assign a derived class to a base class, but not the other way around.
The way to go, is to use polymorphy, i.e., to add an abstract Validate
method to the (abstract) Child
class (unless you can provide a standard implementation in the base class). The derived classes then must override this method and provide an implementation. At runtime, Dynamic dispatch will then call the right implementation.
Related Topics
<Iostream> VS. <Iostream.H> VS. "Iostream.H"
How to Pass Std::String to a Dll
How to Return a Char Array from a Function
Is the Data in Nested Std::Arrays Guaranteed to Be Contiguous
How Do We Explain the Result of the Expression (++X)+(++X)+(++X)
Get Hwnd on Windows with Qt5 (From Wid)
Calling a Const Function Rather Than Its Non-Const Version
Does This Really Break Strict-Aliasing Rules
Why Is Modifying a String Through a Retrieved Pointer to Its Data Not Allowed
Why Do Functions Need to Be Declared Before They Are Used
What Lasts After Using Std::Move C++11
How to Read Output from Cmd.Exe Using Createprocess() and Createpipe()
Is Std::Vector Memory Freed Upon a Clear
Why Does C++ Not Have a Const Constructor
Mesh Class Called with Default Constructor Not Working Opengl C++