Related
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.
In a recent question, someone asked about static methods and one of the answers stated that you generally call them with something like:
MyClassName.myStaticMethod();
The comments on that also stated that you could also call it via an object with:
MyClassName myVar;
myVar.myStaticMethod();
but that it was considered bad form.
Now it seems to me that doing this can actually make my life easier so I don't have to worry about what's static or not (a).
Is there some problem with calling static functions via an object? Obviously you wouldn't want to create a brand new object just to call it:
Integer xyzzy;
int plugh = xyzzy.parseInt ("42", 10);
But, if you already have an object of the desired type, is there a problem in using it?
(a) Obviously, I can't call a non-static method with:
MyClassName.myNonStaticMethod();
but that's not the issue I'm asking about here.
In my opinion, the real use case that makes this so unreadable is something like this. What does the code below print?
//in a main method somewhere
Super instance = new Sub();
instance.method();
//...
public class Super {
public static void method() {
System.out.println("Super");
}
}
public class Sub extends Super {
public static void method() {
System.out.println("Sub");
}
}
The answer is that it prints "Super", because static methods are not virtual. Even though instance is-a Sub, the compiler can only go on the type of the variable which is Super. However, by calling the method via instance rather than Super, you are subtly implying that it will be virtual.
In fact, a developer reading the instance.method() would have to look at the declaration of the method (its signature) to know which method it actually being called. You mention
it seems to me that doing this can actually make my life easier so I don't have to worry about what's static or not
But in the case above context is actually very important!
I can fairly confidently say it was a mistake for the language designers to allow this in the first place. Stay away.
The bad form comment comes from the Coding Conventions for Java
See http://www.oracle.com/technetwork/java/codeconventions-137265.html#587
The reason for it, if you think about it, is that the method, being static, does not belong to any particular object. Because it belongs to the class, why would you want to elevate a particular object to such a special status that it appears to own a method?
In your particular example, you can use an existing integer through which to call parseInt (that is, it is legal in Java) but that puts the reader's focus on that particular integer object. It can be confusing to readers, and therefore the guidance is to avoid this style.
Regarding this making life easier for you the programmer, turn it around and ask what makes life easier on the reader? There are two kinds of methods: instance and static. When you see a the expression C.m and you know C is a class, you know m must be a static method. When you see x.m (where x is an instance) you can't tell, but it looks like an instance method and so most everyone reserves this syntax for instance methods only.
It's a matter of communication. Calling a method on an instance implies you're acting on/with that particular instance, not on/with the instance's class.
It might get super confusing when you have an object that inherits from another object, overriding its static method. Especially if you're referring to the object as a type of its ancestor class. It wouldn't be obvious as to which method you're running.
If I do this in Java to call a method name from a class dynamically, it works.
MainApp app = new MainApp();
Method meth = app.getClass().getMethod("myMethod", MyParameterType.class);
//call method
meth.invoke(app, new MyParameterType("hello"));
But this worked because I know the constructor in the invoke method. But if I were to pass the Method object as a parameter to some other classes, and I don't know who is the constructor, I cannot invoke the method any more. Even if I know, I may not want to create a different object to just make a call to the method. For eg:
//This is in the class call MainApp.java.
//There is a method in MainApp.java that looks this way: myMethod(MyParameterType param);
MainApp app = new MainApp();
OtherClass myClass = new OtherClass();
Method meth = app.getClass().getMethod("myMethod", MyParameterType.class);
myClass.callMe(meth);
//Inside OtherClass.java
public void callMe(Method meth) {
//call method
meth.invoke(########, new MyParameterType("hello"));
}
In this case, what should I put for the ######## parameter? Within the context of OtherClass.java, the base constructor object wouldn't be known. And why would I need if since meth is already a Method type that I just call like a function?
Thanks
Assuming it's an instance method, you've got to have an instance to call the method on, just like anything else. How you get hold of that instance will depend on what you're trying to do; you could pass in a Constructor, or a reference to an existing object, or some interface which will create the instance when you ask it to... we can't really give you any advice on which approach is the most suitable without knowing what you're trying to do.
If it's a static method, you can pass null for the first argument.
What it seems you are looking for or thinking about is the concept of `lambda functions``. Those can be called in isolation.
A Method type is not a standalone method, but more like a 'path' into an object. Compare this with a relative URL like /subscribe.html. Out of context this is pretty useless, but when bundled with a site like www.example.com it makes sense.
As such, Method can only be used in combination with an instance. (edit: as John mentioned, unless it's a static method of course which do not need instances)
If you can safely invoke a method without providing an instance, it should be a static method, in which case any instance provided is ignored, you can give it null.
If you have to provide an instance of the object, there is no way around this.
If the developer who write the method has labelled it non-static incorrectly, I suggest you discuss with them why they did it.
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.
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)