Confusing polymorphism in Java - java

Consider this code (complete class, runs fine, all classes in one class for the sake of brevity).
My questions are after the code listing:
import java.util.LinkedList;
import java.util.List;
class Gadget {
public void switchon() {
System.out.println("Gadget is Switching on!");
}
}
interface switchonable {
void switchon();
}
class Smartphone extends Gadget implements switchonable {
#Override
public void switchon() {
System.out.println("Smartphone is switching on!");
}
}
class DemoPersonnel {
public void demo(Gadget g) {
System.out.println("Demoing a gadget");
}
public void demo(Smartphone s) {
System.out.println("Demoing a smartphone");
}
}
public class DT {
/**
* #param args
*/
public static void main(String[] args) {
List<Gadget> l = new LinkedList<Gadget>();
l.add(new Gadget());
l.add(new Smartphone());
for (Gadget gadget : l) {
gadget.switchon();
}
DemoPersonnel p = new DemoPersonnel();
for (Gadget gadget : l) {
p.demo(gadget);
}
}
}
Questions:
From the compilers point of view, what is the origin of the switchon method in Smartphone? Is it inherited from the base class Gadget? Or is it an implementation of the switchon method mandated by the switchonable interface? Does the annotation make any difference here?
In the main method, first loop: Here, we see a case of runtime polymorphism - i.e., when the first for loop is running, and gadget.switchon() is called, it first prints "Gadget is switching on", and then it prints "Smartphone is switching on". But in the second loop, this runtime resolution does not happen, and the output for both calls to demo is "Demoing a gadget", whereas I was expecting it to print "Demoing a gadget" the first iteration, and "Demoing a smartphone" the second time.
What am I understanding wrong? Why does the runtime resolve the child class in the first for loop, but doesn't do so in the second for loop?
Lastly, a link to a lucid tutorial on runtime/compile-time polymorphism in Java will be appreciated. (Please do not post the Java tutorial trail links, I didn't find the material particularly impressive when discussing the finer nuances in respectable depth).

This is how it works shortly:
Compiling time
The compiler defines the required signature for the requested method
Once the signature is defined, the compiler starts to look for it in the type-Class
If it finds any compatible candidate method with the required signature proceeds, otherwise returns an error
Runtime
During execution JVM starts to look for the candidate method with the signature as exactly defined during the compiling-time.
The search for the executable method actually starts from the real Object implementation Class (which can be a subclass of the type-Class) and surf the whole hierarchy up.
Your List is defined with type Gadget.
for (Gadget gadget : l) {
gadget.switchon();
}
When you ask for gadget.switchon(); the compiler will look for the switchon() method in the Gadget class and as it's there the candidate signature is simply confirmed to be switchon().
During the execution, the JVM will look for a switchon() method from the Smartphone Class and this is why it is displaying the correct message.
Here is what happens in the second for-loop
DemoPersonnel p = new DemoPersonnel();
for (Gadget gadget : l) {
p.demo(gadget);
}
The signature in this case is for both objects demo(Gadget g), this is why for both iterations method demo(Gadget g) is executed.
Hope it helps!

From the compilers point of view, what is the origin of the switchon method in Smartphone? Is it inherited from the base class Gadget? Or is it an implementation of the switchon method mandated by the switchonable interface?
The second case
Does the annotation make any difference here?
Not at all, #Override is just a helper, whe you use it you are telling the compiler: "my intention is to override the method from a supertype, please throw an exception and don't compile this if it is not overriding anything"
About the second question, in this case the method that better match acording to its signature is the one to be called. At run time in the second loop your objects have the supertype "associated", that's the reason public void demo(Gadget g) will be called rather than public void demo(Smartphone g)

1.It shouldn't matter. Because it is extending Gadget, if you don't override and call switchon() from a smartphone, it would say "Gadget is switching on!". When you have both an interface and a parent class with the same method, it really doesn't matter.
2.The first loop works and the second doesn't because of the way java looks at objects. When you call a method from an object, it takes the method directly from that object, and thus knows whether smartphone or gadget. When you send either a Smartphone or Gadget into an overloaded method, everything in that class is called a Gadget, whether it is actually a smartphone or not. Because of this, it uses the gadget method. To make this work, you would want to use this in the demo(Gadget g) method of DemoPersonnel:
if(gadget instanceof Smartphone){
System.out.println("Demoing a gadget");
}else{
System.out.println("Demoing a smartphone");
}
Sorry I don't have a link to a tutorial, I learned through a combination of AP Computer Science and experience.

Answering question 2 first: In the second loop your passing an object typed as a Gadget therefore the best match in the demo class is the method taking a gadget. this is resolved a compile time.
for question 1: the annotation does not make a difference. it just indicates that you overriding (implementing) method in the interface.

For compiler, Smartphone inherits switchon() method "implementation" from Gadget and then Smartphone overrides inherited implementation with its own implementation. On the other hand switchonable interface dictates Smartphone to provide an implementation of switchon() method definition and which was fulfilled by the implementation overridden in Smartphone.
First case is working as you expected because it is indeed a case of polymorphism i.e. you have one contract and two implementations - one in Gadget and another in Smartphone; where later has "overridden" the former implementation. Second case "should not" work as you expect it to, because there's only one contract and one implementation. Do note that you are "not overriding" the demo() method, you are actually "overloading" the demo() method. And, overloading means two "different" unique method definitions that only shares the "same name". So, it is a case of one contract and one implementation, when you call demo() with Gadget parameter, because compiler will match the method name with exact method parameter type(s) and by doing so will call "different methods" in both iterations of the loop.

about the second question :
In Java, dynamic method dispatch happens only for the object the method is called on, not for the parameter types of overloaded methods.
Here is a link to the java language specification.
As it says :
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).
so basically :the compile time type of the method parameters is used to determine the signature of the method to be called
At runtime, the class of the object the method is called on determines which implementation of that method is called, taking into account that it may be an instance of a subclass of the declared type that overrides the method.
In your case when you create object of a child class by new child(); and pass it on to the overloaded method, it has superclass type associated. Hence overloaded method with parent's object is called.

The annotation does not make any difference here. Techinically is like you are doing both things: overriding parent switchon() and implementing the switchon() interface method in one shot.
Method lookup (with respect to method arguments) is not done dynamically (at runtime) but statically at compile-time. Looks strange but thats how it works.
Hope this helps.

The compiler selects a method signature based on the declared type of the "this" pointer for the method and the declared type of the parameters. So since switchon receives a "this" pointer of Gadget, that is the version of the method that the compiler will reference in its generated code. Of course, runtime polymorphism can change that.
But runtime polymorphism only applies to the method's "this" pointer, not the parms, so the compiler's choice of method signature will "rule" in the second case.

Related

Java - (Anonymous subclass) overriding method during object instance construction

I am maintaining some Java 8 code which looks like this:
Class Entity {
protected Model theModel;
public Entity() {
init();
}
protected void init() {
this.theModel = new Model();
}
}
Class Model {
}
Class SubModel extends Model {
}
main {
Entity newEntity = new Entity() {
#Override
protected void init() {
this.theModel = new SubModel();
}
};
}
The code currently compiles and runs correctly, but I now need to update it.
My question are:
How is the override of the init() method working at all, during the construction of the newEntity?
What is the correct terminology for this method override included in the object constructor statement?
My research so far suggests that Java cannot dynamically override methods - cannot do overrides on this basis, because method overrides are per-class not per-object. But this code snippet seems to show that Java can do it in practice?
UPDATE: Note that the creation of the newEntity in main creates an anonymous sub-class, and the init() method is being overridden for that anonymous sub-class only. This is explained better in the two excellent answers below.
As far as I can tell there is nothing special here, is just classical constructor chaining and polymorphism applied to virtual method invocations.
When you instantiate your anonymous class, it will automatically invoke its default constructor (which is automatically given by the compiler), before its default constructor succeeds it must first invoke its parent class default constructor, which in turn will invoke the init() method, which, since it has been overridden by your anonymous class, polymorphically, ends up calling the init method in the child class, which initializes the model to your SubModel instance.
Joshua Bloch has a few interesting arguments against this pattern in his famous book Effective Java, in the section "Item 17: Design and document for inheritance or else prohibit" he wrote:
“There are a few more restrictions that a class must obey to allow
inheritance. Constructors must not invoke overridable methods,
directly or indirectly. If you violate this rule, program failure will
result. The superclass constructor runs before the subclass
constructor, so the overriding method in the subclass will get invoked
before the subclass constructor has run. If the overriding method
depends on any initialization performed by the subclass constructor,
the method will not behave as expected. To make this concrete, here's
a class that violates this rule:”
He then proceeds to give an example which you would do well to study:
“Here's a subclass that overrides the overrideMe, method which is
erroneously invoked by Super's sole constructor:”
public class Super {
    // Broken - constructor invokes an overridable method
    public Super() {
        overrideMe();
    }
    public void overrideMe() {
    }
}
public final class Sub extends Super {
    private final Date date; // Blank final, set by constructor
    Sub() {
        date = new Date();
    }
    // Overriding method invoked by superclass constructor
    #Override public void overrideMe() {
        System.out.println(date);
    }
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.overrideMe();
    }
}
“You might expect this program to print out the date twice, but it
prints out null the first time, because the overrideMe method is
invoked by the Super constructor before the Sub constructor has a
chance to initialize the date field. Note that this program observes a
final field in two different states! Note also that if overrideMe had
invoked any method on date, the invocation would have thrown a
NullPointerException when the Super constructor invoked overrideMe.
The only reason this program doesn't throw a NullPointerException as
it stands is that the println method has special provisions for
dealing with a null argument.”
So, as you can see, and as Joshua Bloch explained so well, the risks lurk in the shadows: in the possibilities of what you can do in the overridden method, where you have license to touch instance variables that the constructor chain has not yet had a chance to initialize. The point is that you should not be allowed to touch the object state until it has been fully initialized by the constructor chain.
You might say that in your particular case that does not happen, since you are not illegally altering state and your overridden method is protected, not public, but the problem is that any person touching this code needs a very clear understanding of all these things happening under the hood, happening in places other than your current code. During maintenance it is easy to make a serious mistake, particularly when you or some other developer, comes back here to make changes, possibly months or even years after this was originally defined, and having lost context of all these dangers somebody introduces a bug that will be really hard to find and fix.
If it is in fact exactly as you are showing us, and there is no significant part of the picture missing, then the code that you have to maintain is bad, and maintenance of bad code is very troublesome.
Invoking an overridable from within a constructor is legal, but it is very bad practice, because the overridable will be invoked on a descendant whose constructor has not yet been invoked, which is catastrophic. It may not matter in trivial examples, where descendants have empty constructors, but it is bound to cause major trouble later, when things become more complicated, and a descendant suddenly one day needs to have a non-empty constructor.
And with the passage of time things do tend to become more complicated.
A halfway decent IDE would have issued a big fat warning on the invocation of the overridable from within the constructor. This in turn means that the code was written with an insufficient number of warnings enabled, which probably means that it is full of problems of this kind.
The correct terminology for this method override included in the object constructor is: Wrong.
You cannot correct this without some major refactoring. Either the model needs to be passed as a constructor parameter, or the constructor must live with the fact that the model cannot be known at all during construction.
Your question about "dynamically" overriding methods is a bit strange, and it is probably unnecessarily complicating things. Virtual method dispatching is done internally by means of a virtual method table. Each class has its own virtual method table, which never changes. However, when a constructor executes, the this pointer points to the actual (descendant) instance, so the virtual method table in effect is that of the descendant. So, when the constructor calls an overridable, the overridable of the descendant is invoked.
That's different from C++, where the virtual method table in effect at construction time is the virtual method table of the class declaring the constructor, (irrespective of whether it has been subclassed,) so when you call a virtual method from within a C++ constructor you are not invoking any overriding methods.

Use of method in superclass that has been overridden in a subclass, depending on the type of the objects that call it

I am looking for a way to call different definitions of a (overridden) method depending on the type of the objects that are calling the method. This should make more sense when I labour the point below.
I have two classes defined as follows:
public class SuperClass{
public method1(){
if (objects are of type SuperClass and not SubClass){ //pseudocode
method2();
}
//do some more stuff
}
public method2(){
//do stuff
}
}
public class SubClass extends SuperClass{
#Override
public method1(){
method2();
super.method1();
}
#Override
public method2(){
//do stuff
}
}
From these two classes I am working with 3 objects, call them dog, cat, and bird. dog and cat are both objects of type SuperClass, whereas bird is of type SubClass.
You notice that all the objects follow the same basic procedure in the code, their method1() calls upon method2() before doing anything else. The difference between them is obviously that SubClass overrides method2(): bird has a different method2().
Currently my code is working how I want it, but I'm looking for a more elegant solution (if there is one). You can see from my code above how I've stepped around the issue at hand: in SuperClass I basically check that the objects are of type SuperClass. In my actual program that pseudocode line looks more like this (still "pseudocodey"):
if(this.toString().equals("Dog") || this.toString().equals("Cat")){
method2();
}
And bird calls it's own definition of method2() before calling the original definition of method1(). Basically both classes are dealing with their own local definition of method2().
My idea of a more elegant is as follows: completely remove the overridden definition of method1() from SubClass and be able to call the overridden definition of method2() from within SuperClass at the appropriate time (i.e. when the object I'm dealing with is bird).
I basically tried the above exactly as I wrote it, but the bird object ended up using the definition of method2() that is in SuperClass rather than the one in SubClass.
Can this be done, if so, how?
Inheritance and Overriding works exactly as you want it to, without you having to check if the instance if super or sub class.
Just do,
public class SuperClass{
public method1(){
method2(); // Note that you don't need any instance check here.
//do some more stuff
}
public method2(){
SOP("Super method2");
}
}
public class SubClass extends SuperClass{
#Override
public method2(){ // Note that you don't have to override method1
SOP("SUB method2")
}
}
In this case, if you call, method1() with an Super class object, it will call method2() of super class and print Super method2.
If you call, method1() with a Sub class object, it will call method2() of sub class and print Sub method2.
You should not check for the type in the superclass method. Not with the posted ugly toString() method, not with instanceof either. Let polymorphism work for you.
The whole concept of polymorphism is that you can call a method on a superclass type, and the object will behave as it's actual type. The standard textbook example goes something like this:
Cat cat = new Cat();
Animal animal = cat;
animal.speak();
Imagine you didn't see the animal = cat assignment. You just have an Animal. You don't know if it's a cat, or a dog or an elephant, all you know is that has a speak method. The object will behave according to its actual type, without needing to check types inside, thanks to polymorphism.
You can use the instanceOf() method to check if an object is an instance of another class. However this will return true for all super classes as well.
However I believe what you are saying is that you want sub classes to call their own version of a method if they have over ridden it. This will happen automatically due to Polymorphism
In order to call different definitions of a method depending on the type of the objects that are calling the method you might to do overloading, This is how it works
If a suitable function is found, that function is called. "Suitable" in this context means one of the following:
• An exact match was found.
• A trivial conversion was performed.
• An integral promotion was performed.
• A standard conversion to the desired argument type exists.
• A user-defined conversion (either conversion operator or constructor) to the desired argument type exists.
• Arguments represented by an ellipsis were found.
The compiler creates a set of candidate functions for each argument. Candidate functions are functions in which the actual argument in that position can be converted to the type of the formal argument.
A set of "best matching functions" is built for each argument, and the selected function is the intersection of all the sets. If the intersection contains more than one function, the overloading is ambiguous and generates an error. The function that is eventually selected is always a better match than every other function in the group for at least one argument. If this is not the case (if there is no clear winner), the function call generates an error.

Overloading is compile-time polymorphism. Really?

I do know the syntactical difference between overriding and overloading. And I also know that overriding is run-time polymorphism and overloading is compile-time polymorphism. But my question is: "Is overloading is really compile-time polymorphism? Is the method call really solving at compile time?". To clarify my point, let's consider an example class.
public class Greeter {
public void greetMe() {
System.out.println("Hello");
}
public void greetMe(String name) {
System.out.println("Hello " + name);
}
public void wishLuck() {
System.out.println("Good Luck");
}
}
Since all of the methods greetMe(), greetMe(String name), wishLuck() are public, they all can be overriden(including overloaded one), right? For example,
public class FancyGreeter extends Greeter {
public void greetMe() {
System.out.println("***********");
System.out.println("* Hello *");
System.out.println("***********");
}
}
Now, consider the following snippet:
Greeter greeter = GreeterFactory.getRandomGreeter();
greeter.greetMe();
The getRandomGreeter() method returns a random Greeter object. It may either return an object of Greeter, or any of its subclasses, like FancyGreeter or GraphicalGreeter or any other one. The getRandomGreeter() will create the objects either using new or dynamically load the class file and create object using reflection(I think it is possible with reflection) or any other way that is possible. All of these methods of Greeter may or may not be overriden in subclasses. So the compiler has no way to know whether a particular method(overloaded or not) is overriden. Right? Also, wikipedia says on Virtual functions:
In Java, all non-static methods are by default "virtual functions".
Only methods marked with the keyword final, which cannot be overridden,
along with private methods, which are not inherited, are non-virtual.
Since, virtual functions are resolved at run-time using dynamic method dispatch, and since all non private, non final methods are virtual(whether overloaded or not), they must be resolved at run-time. Right?
Then, How can overloading still be resolved at compile-time? Or, is there anything that I misunderstood, or am I missing?
Every 'Greeter' class has 3 virtual methods: void greetMe(), void greetMe(String), and void wishLuck().
When you call greeter.greetMe() the compiler can work out which one of the three virtual methods should be called from the method signature - ie. the void greetMe() one since it accepts no arguments. Which specific implementation of the void greetMe() method is called depends on the type of the greeter instance, and is resolved at run-time.
In your example it's trivial for the compiler to work out which method to call, since the method signatures are all completely different. A slightly better example for showing the 'compile time polymorphism' concept might be as follows:
class Greeter {
public void greetMe(Object obj) {
System.out.println("Hello Object!");
}
public void greetMe(String str) {
System.out.println("Hello String!");
}
}
Using this greeter class will give the following results:
Object obj = new Object();
String str = "blah";
Object strAsObj = str;
greeter.greetMe(obj); // prints "Hello Object!"
greeter.greetMe(str); // prints "Hello String!"
greeter.greetMe(strAsObj); // prints "Hello Object!"
The compiler will pick out the method with the most specific match using the compile-time type, which is why the 2nd example works and calls the void greetMe(String) method.
The last call is the most interesting one: Even though the run-time type of strAsObj is String, it has been cast as an Object so that's how the compiler sees it. So, the closest match the compiler can find for that call is the void greetMe(Object) method.
Overloaded methods can still be overridden, if that is what you ask.
Overloaded methods are like different families, even though they share the same name. The compiler statically chooses one family given the signature, and then at run time it is dispatched to the most specific method in the class hierarchy.
That is, method dispatching is performed in two steps:
The first one is done at compile time with the static information available, the compiler will emit a call for the signature that matches best your current method parameters among the list of overloaded methods in the declared type of the object the method is invoked upon.
The second step is performed at run time, given the method signature that should be called (previous step, remember?), the JVM will dispatch it to the most concrete overridden version in the actual type of receiver object.
If the method arguments types are not covariant at all, overloading is equivalent to having methods names mangled at compile time; because they are effectively different methods, the JVM won't never ever dispatch them interchangeably depending on the type of the receiver.
What is polymorphism?
Acc. to me: if an entity can be represented in more than one forms, that entity is said to exhibit polymorphism.
Now, lets apply this definition to Java constructs:
1) Operator overloading is compile time polymorphism.
For example, + operator can be used to add two numbers OR to concatenate two strings. it's an example of polymorphism strictly saying compile-time polymorphism.
2) Method overloading is compile time polymorphism.
For example, a method with same name can have more than one implemntations. it's also a compile-time polymorphism.
It's compile-time because before execution of program compiler decides the flow of program i.e which form will be used during run-time.
3) Method overriding is run-time polymorphism.
For example, a method with same signature can have more than one implemenations. it's a run time polymorphism.
4) Base class use in place of derived class is run time polymorphism.
For example, an interface reference can point to any of it's implementor.
It's run-time because the flow of program can't be known before execution i.e. only during run-time it can be decided that which form will be used.
I hope it clears a bit.
Overloading in this respect means that the type of the function is statically determined at compile time as opposed to dynamic dispatch.
What really happens behind the scenes is that for a method named "foo" with types "A" and "B" two methods are created ("foo_A" and "foo_B"). Which of them is to be called is determined at compile-time (foo((A) object) or foo((B) object) result in foo_A being called or foo_B). So in a way this is compile-time polymorphism, although the real method (i.e. which implementation in the class hierarchy to take) is determined at runtime.
I have strong objection to call method overloading as compile time polymorphism.
I agree that method overloading is static binding(compile time) but i didn't see polymorphism in that.
I tried to put my opinion in my question to get clarification. you can refer this link.

Java overloading and overriding

We always say that method overloading is static polymorphism and overriding is runtime polymorphism. What exactly do we mean by static here? Is the call to a method resolved on compiling the code? So whats the difference between normal method call and calling a final method? Which one is linked at compile time?
Method overloading means making multiple versions of a function based on the inputs. For example:
public Double doSomething(Double x) { ... }
public Object doSomething(Object y) { ... }
The choice of which method to call is made at compile time. For example:
Double obj1 = new Double();
doSomething(obj1); // calls the Double version
Object obj2 = new Object();
doSomething(obj2); // calls the Object version
Object obj3 = new Double();
doSomething(obj3); // calls the Object version because the compilers see the
// type as Object
// This makes more sense when you consider something like
public void myMethod(Object o) {
doSomething(o);
}
myMethod(new Double(5));
// inside the call to myMethod, it sees only that it has an Object
// it can't tell that it's a Double at compile time
Method Overriding means defining a new version of the method by a subclass of the original
class Parent {
public void myMethod() { ... }
}
class Child extends Parent {
#Override
public void myMethod() { ... }
}
Parent p = new Parent();
p.myMethod(); // calls Parent's myMethod
Child c = new Child();
c.myMethod(); // calls Child's myMethod
Parent pc = new Child();
pc.myMethod(); // call's Child's myMethod because the type is checked at runtime
// rather than compile time
I hope that helps
Your are right - calls to overloaded methods are realized at compile time. That's why it is static.
Calls to overridden methods are realized at run-time, based on the type on which the method is invoked.
On virtual methods wikipedia says:
In Java, all non-static methods are by default "virtual functions." Only methods marked with the keyword final are non-virtual.
final methods cannot be overridden, so they are realized statically.
Imagine the method:
public String analyze(Interface i) {
i.analyze();
return i.getAnalysisDetails();
}
The compiler can't overload this method for all implementations of Interface that can possibly be passed to it.
I don't think you can call overloading any sort of polymorphism. Overloaded methods are linked at compile time, which kind of precludes calling it polymorphism.
Polymorphism refers to the dynamic binding of a method to its call when you use a base class reference for a derived class object. Overriding methods is how you implement this polymorphic behaviour.
i agree with rachel, because in K&B book it is directly mentioned that overloading does not belong to polymorphism in chapter 2(object orientation). But in lots of places i found that overloading means static polymorphism because it is compile time and overriding means dynamic polymorphism because it s run time.
But one interesting thing is in a C++ book (Object-Oriented Programming in C++ - Robert Lafore) it is also directly mentioned that overloading means static polymorphism.
But one more thing is there java and c++ both are two different programing languages and they have different object manipulation techniques so may be polymorphism differs in c++ and java ?
Method Overloading simply means providing two separate methods in a class with the same name but different arguments while method return type may or may not be different which allows us to reuse the same method name.
But both methods are different hence can be resolved by compiler at compile time that's is why it is also known as Compile Time Polymorphism or Static Polymorphism
Method Overriding means defining a method in the child class which is already defined in the parent class with same method signature i.e same name, arguments and return type.
Mammal mammal = new Cat();
System.out.println(mammal.speak());
At the line mammal.speak() compiler says the speak() method of reference type Mammal is getting called, so for compiler this call is Mammal.speak().
But at the execution time JVM knows clearly that mammal reference is holding the reference of object of Cat, so for JVM this call is Cat.speak().
Because method call is getting resolved at runtime by JVM that's why it is also known as Runtime Polymorphism and Dynamic Method Dispatch.
Difference Between Method Overloading and Method Overriding
For more details, you can read Everything About Method Overloading Vs Method Overriding.
Simple Definition - Method overloading deals with the notion of having two or more methods(functions) in the same class with the same name but different arguments.
While Method overriding means having two methods with the same arguments, but different implementation. One of them would exist in the Parent class (Base Class) while another will be in the derived class(Child Class).#Override annotation is required for this.
Check this :
Click here for a detailed example
Property Over-loading Overriding
Method Names -------------->must be Same----------------must be same
Arg Types------------------>must be Different(at least arg)
Method Signature
Return Type
Private,Static,Final
Access Modifier
try/Catch
Method Resolution
First, I want to discuss Run-time/Dynamic polymorphism and Compile-time/static polymorphism.
Compile-time/static polymorphism:- as its name suggests that it bind the function call to its appropriate Function at compile time. That means the compiler exactly know which function call associated to which function. Function overloading is an example of compile time polymorphism.
Run-time/Dynamic polymorphism:-In this type of polymorphism compiler don't know which functions call associates to which function until the run of the program. Eg. function overriding.
NOW, what are the function overriding and function overloading???
Function Overloading:- same function name but different function signature/parameter.
eg. Area(no. of parameter)
{ -------------
----------------
return area;}
area of square requires only one parameter
area of rectangle requires two parameters(Length and breadth)
function overriding:- alter the work of a function which is present in both the Superclass and Child class.
eg. name() in superclass prints "hello Rahul" but after overring in child class it prints "hello Akshit"
Tried to cover all differences
Overloading Overriding
Method Name Must be same Must be same
Argument Types Must be same Must be different
Return Type No restriction Must be same till 1.4V
but after 1.4V
co- variants
were introduced
private/static/final Can be overloaded Cannot be overridden
Access Modifiers No restriction Cannot reduce the scope
Throws keyword No restriction If child class method
throws a checked
exception the parent
class method must throw
the same or the
parent exception
Method Resolution Taken care by compiler Taken care by JVM based
based on reference types on run-time object
Known as Compile-Time Polymorphism, RunTime Polymorphism,
Static Polymorphism, or dynamic polymorphism,
early binding late binding.

How does Java pick which overloaded function to call?

This is a purely theoretical question.
Given three simple classes:
class Base {
}
class Sub extends Base {
}
class SubSub extends Sub {
}
And a function meant to operate on these classes:
public static void doSomething(Base b) {
System.out.println("BASE CALLED");
}
public static void doSomething(Sub b) {
System.out.println("SUB CALLED");
}
It seems that the followign code:
SubSub ss = new SubSub();
doSomething(ss);
could legitimately result in printing either BASE CALLED, or SUB CALLED, since SubSub can be casted to both of those. In fact, removing the Sub version of the function causes BASE CALLED to be printed. What actually happens is that "SUB CALLED" is printed. This seems to mean that which function is called doesn't depend on the order the functions are defined in, as the Base version was called first.
Does Java just look at all the different versions of the function and pick the one which requires the smallest traversal up the inheritance stack? Is this standardized? Is it written out in any documentation?
The formal specification can be found in part 15.12.2.5 of the Java Language Specification (JLS). Thanks to generics this is pretty complicated, so you might want to look at same section of the first edition of the JLS.
It basically says that the compiler tries to find a version of the method where all parameters including the object the method is called upon are most specific. If no such method exists (e.g. since you have method(Base, Sub) and method(Sub, Base) but not method(Sub, Sub)), then the compilation fails.
Note that the actual choice of method depends on the dynamic type of the target object for instance methods, but not for the parameters. Your example would still work the same on the instance level.
You should be able to give the compiler a helping hand by casting or redeclaring the type of ss. If the declared type of the variable matches a signature exactly then everything is clear for the compiler and maintenance programmers as well. It doesn't matter if you then assign a more specific type as long as the declared type matches.
As far as I know, Java and C++ make this decision at compilation time (since these are static functions that are not dynamically dispatchable) based on the most specific matching that they can make. If your static type is SubSub and you have an overload that takes SubSub, this is the one that will be invoked. I'm fairly sure it's in both standards.
If you have a reference or pointer to Base, even if it contains a Sub or a SubSub, you will match the version that takes a Base because at compile time, that is the only assurance that the compiler has.
When you have overloaded static methods then it calls that method that is defined immediately in the class which is invoking the method. If however, no method is defined in the calling class then it will invoke the method inherited from its immediate parent class.
In your case there are two overloaded methods both of which can accept SubSub as parameter. the compiler checks for the most specific match and goes for it. But the most specific match is generally the lowest in the type hierarchy.
EDITED
Removed the conflicting statement. Two methods in classes that are at the same type hierarchy level can't be in ambiguous state for the compiler to choose. This ambiguity is possible only in the case of multiple inheritance.
Java binds methods dynamically (in runtime, depending on object instance type, not reference type) but only in context of one method signature. Java binds method signature statically (at compilation time).
In other words, Java makes decision what method (signature) should be called in compile time (statically - reference based - overloading). In runtime Java will take that signature, find proper object in object type hierarchy and execute that method on that dynamically binded object.
Overloading -> what (method signature at compilation time)
Overriding -> from where (object in type hierarchy at runtime)

Categories