Java method overriding - java

I am really confused as to how overriding is very different from overloading in java since when I implement overloading I call a method by the same name but different signature that is a different datatype parameter or a different return type. In overriding also I call different methods(Different block of code) by passing objects of different type. Now when I am passing different types of objects its the same as passing a different datatype as different classes represent different user-defined datatype. So apart from the difference of Overloading being in the same class and overriding being in different classes are the two conceptually the same?

Override means that you change the functionality of a method (you overwrite what that method does).
Overload means that you keep the method name and return type , but you have different input paremeters.
The two concepts are very different.
While in override you have a different functionality for the SAME method, with overload you have two DIFFERENT methods with the SAME name .
!EDIT
You can overload a method to have a different return type only if you have different input parameters. You cannot overload a method by only changing it's return type.

When you overload a method, you allow the method to be invoked through different signature..
For example
add(int a, int b);
add(int a, int b, int c);
add(int a, int b, int c, int d);
As you see here, all the three overloads are having different signatures..
However, when you over-ride a method, You must have the same signature as the method you are trying to override..
Hence overloading requires same name whereas over-riding requires same signature, but different functioning..

public class animal{
public String sayHi(){
return "hi im animal";
}
}
public class dog extends animal{
//you are overriding the method by changing its funcionality instead of returning "hi im animal" it will return "hi this is dog"
public String sayHi(){
return "hi this is dog";
}
}
public class cat extends animal{
//you are overloading the method by adding a parameter catName.
public String sayHi(String catName){
return "hi this is "+ catName;
}
}
overriding and overloading use the same method name but different functionalities,
overloading as the name implies you are putting some stuff(parameters) inside the method. it is like a stuff toy. overloading with cotton so it could be fluffy.
this is polymorphism which is a single method but with different behavior.

The most significant diference is that overriding works at runtime and overloading at compile time.
That is the reason, that lots of people in the begining (me too) don't understand that polymorphism do not work for overloaded methods.

No, they aren't the same concept.
When overriding you change the normal behaviour of existing method.
When overload you add a new method that will do or is expected to do the same things in background. If you do an overload you want to have the chance of call the same method with different arguments to do same thing, not to change the behaviour.
I think that they aren't conceptually the same.

Overloading happens at compile time
Another important point to remember is that overloading is a compile time phenomenon. This just means that the compiler determines whether a given method(s) is correctly overloaded.
Overridden method provide virtual method invocation feature.
Overriding methods is completely different from overloading methods. If a derived class requires a different definition for an inherited method, then that method can be redefined in the derived class. This would be considered overriding.
An overridden method would have the exact same method name, return type, number of parameters, and types of parameters as the method in the parent class, and the only difference would be the definition of the method.
Read more about Polymorphism
So apart from the difference of Overloading being in the same class and overriding being in different classes are the two conceptually the same?
No, method overloading can span in multiple classes as well. You can provide another method with the same name in child class.
Learn more...

Thank you #MichaelCMS for answer. I added some sample code. I hope it helps.
public class Base {
public void sayHello() {
System.out.println("Base.sayHello()");
}
}
public class Child extends Base {
/*If you remove the comments, you can see that overriden method is called.*/
// this is method overriding
// public void sayHello() {
// System.out.println("Child.sayHello()");
// }
//this is method overloading
public void sayHello(String name) {
System.out.println("Child.sayHello()-> " + name);
}
//This is method overloading
public int sayHello(String name, String surname) {
System.out.println("Child.sayHello()-> " + name + " " + surname );
return 0;
}
public static void main(String[] args) {
Child child = new Child();
child.sayHello();
child.sayHello("Filiph");
child.sayHello("Filiph", "Jenssen");
}
}
prints out
Base.sayHello()
Child.sayHello()-> Filiph
Child.sayHello()-> Filiph Jenssen

Related

Matching function name but different arguments

Studying "cracking the coding interview" in Java, on page 51 I came across:
void permutation(String str){
permutation(str,"");
}
void permutation(String str, String prefix){
if(str.length()==0){
System.out.println(prefix);
} else{
for(int i=0;i<str.length();i++){
String rem=str.substring(0,i)+str.substring(i+1);
permutation(rem,prefix+str.charAt(i));
}
}
}
I get that the first permutation function takes a string and calls the second permutation function which does all the work. However, isn't the second permutation a redeclaration of the first permutation function? How will Java recognize and use the first permutation function and not overwrite it?
How will java recognize and use the first permutation function?
When you call the method, Java will see what you're trying pass into it. Based on the arguments you pass, it will decide which 'version' of the method you are trying to use.
Like others have said - this is method overloading
Unlike in Python, in Java these two declarations live side-by-side -- the second doesn't replace the first. In Java, the rule is roughly that when you call a method with multiple definitions (aka an "overloaded" method), Java will look for the one that best matches the arguments you called it with and run that method. So permutation("hi") invokes the first version, and permutation("hi", "") calls the second.
The fundamental difference here is that in Python you can imagine the interpreter reading the definitions one at a time and replacing its overall definition of permutation every time it gets a new definition. In Java, you have to think of it as reading all the definitions of permutation at once, and calling the most appropriate one for any given invocation.
(A consequence of this is that Java also checks at compile-time that every overloaded version of a method is callable: for instance, if you wrote two versions of permutation that both took just a string as their argument, the compiler would give you an error and wouldn't compile your program at all. In python you'd just get the second definition.)
To explain what the semantics are, we need to take a look at how Java methods are differentiated.
In Java, a method is identified by its signature. JLS §8.4.2 specifies that
Two methods have the same signature if they have the same name and argument types.
Important to note is that the return type of a method is not part of a method's signature. Thus if one would write:
public class Foo {
void bar(String baz) {
}
String bar(String baz) {
}
}
Both methods would have the same signature. In Java, this would lead to a compilation error since it is not allowed to have two methods with the same signature in the same class.
The behaviour changes if we take inheritance into the picture:
public class Foo {
void bar(String baz);
}
public class Zoo extends Foo {
#Override
void bar(String baz);
}
In this case, class Zoo overrides method bar(...) of class Foo. Note that the annotation is not responsible for the behaviour and merely a compile-time check to ensure that there is a method void bar(String baz) in at least one parent-class.
The code presented has two method with same name, but different signatures. This is called Overloading in Java. Thus, the method are treated as not "equal". You could rename one of those method and they would not be more or less "equal".
To make things even weirder, if methods are overloaded, the signature for the method to call is made at compile-time. That means that only the static types of parameters can be considered. Let us look at the following code and figure out what the result is:
public class Test {
public static void main(final String... args) {
final String s = "foo";
final Object o = s;
print(s);
print(o);
}
private static void print(final String s) {
System.out.println("Called with String parameter");
}
private static void print(final Object o) {
System.out.println("Called with Object parameter");
}
}
Ideon demo
Now what is the static type of s? It is the type to the left, where s was declared, thus print(final String s) is called and "Called with String parameter" is printed. What is the static type of o? Again, it is the type to the left, where o was declard, and thus print(final Object o) is called and "Called with Object parameter" is printed out. One could argue that in this trivial example, the compiler could figure out that the type of o can only be String, but basing this behaviour on the ability of the compiler to recognize types at compile-time makes it only more confusing.
In java, the whole class is loaded before a method is executed.
This means that the second method is loaded/ready before the first method is executed and the first method is loaded/ready before the second method is executed.
This allows to call a method recursively, and to call a method that will be declared later.
Also, the method is overloaded.
In java, it's possible to create multiple methods with the same name in the same class if the parameters are different. The methods will be treated as different, deoending of the argument that are passed to the method.
In other words, the name alone does not define which method is called but the signature, including the parameters(not the return value)

Reference types in runtime

My included code's output is pretty ugly, but it's just a code for understanding how different things may work in Java. The questioned line is marked with comments on the bottom half of the code.
class CsTorta extends Torta{
public CsTorta retegez(CsTorta a){
....
}
public CsTorta retegez(Torta a){
System.out.println("This method"); //<-----it calls this one and not the one above
....
}
}
public class NewClass {
public static void main(String[] args) {
Torta tt=new Torta(5);
Torta tcs=new CsTorta(3);
CsTorta cs=new CsTorta(4);
System.out.println("");
System.out.println(tcs.retegez(tcs)); //The line in question uses the cstorta retegez method (marked with "This method")
}
}
While the tcs's type in coding-time is the reference type, in runtime when i call the tcs.retegez method it recognizes its a cstorta type, but the parameter which is the same tcs remains the reference type (thats why it uses the cstorta marked method).
My question is: Is my conclusion correct: that the program only checks the "real" type of the object if it calls a method, and uses the reference type if it does not?
That's pretty much correct. What is needed here is understanding the difference between overloading and overriding.
Overriding occurs when you have a class that declares an instance method, and a subclass that declares the same method (same name, same parameters--the result type is usually the same but could be a subclass). There are multiple methods to choose from, but the exact method is determined at run time.
public class A {
public void method1(String s1, int s2) { ... }
}
public class B extends A {
#Override
public void method1(String s1, int s2) { ... }
}
A object = new B();
object.method1("xxx",2);
The decision about which method1 is run isn't made until run time. object's real type is B, so the method1 declared in B is called.
Overloading is when two methods with the same name, but different parameters, are both present. By different parameters, I mean that the number of parameters is different, or the number of parameters is the same but the types are different. That is, they have different signatures. In that case, the decision on which method to call is made at compile time. (You can have a case where both overriding and overloading occur. The decision about which parameter signature to choose is made at compile time; but if there are multiple overriding methods with the same signature, the choice between those methods is made at run time.)
The key thing to remember is that if the decision is made at compile time, the compiler will not know what the "real" type of the object is. All it knows is how you've declared it. Thus:
public CsTorta retegez(CsTorta a){ // Number 1
....
}
public CsTorta retegez(Torta a){ // Number 2
System.out.println("This method"); //<-----it calls this one and not the one above
....
}
These are overloaded methods.
Your code looks like:
Torta tcs = // the compiler doesn't care
System.out.println(tcs.retegez(tcs));
The compiler has to decide whether to call Number 1 or Number 2. All the compiler knows is that the parameter is a Torta. The actual value could be an object of Torta, CsTorta, or any other class. Or it could be null (all right, you can't call tcs.retegez if it's null, but if you said tcs.retegez(tcs2), then tcs2 could be null.) The compiler doesn't know, and doesn't care. All it knows is that it was declared as a Torta, so it chooses the overloaded method with the Torta parameter.
(To clarify further: the compiler will choose the deepest subclass it can. Example:)
class AnotherTorta extends Torta { ... }
class YetAnotherTorta extends CsTorta { ... }
AnotherTorta t3 = // whatever
YetAnotherTorta t4 = // whatever
tcs.retegez(t3);
// since AnotherTorta can't be cast to CsTorta, it chooses the Torta parameter
tcs.retegez(t4);
// here, t4 can be cast to either a Torta or CsTorta parameter, so it chooses the subclass, CsTorta

Why java does not allow to change return type in case of method overriding

I have class A as:
public class A {
int sayHello(int i,int j){
return i+j;
}
}
Another class B as:
public class B extends A {
#Override
int sayHello(int i, int j) {
return i+j;
}
}
If I change return type of method sayHello(int,int) of class A from int to float it shows an error because as per the overriding rule return types are also considered thats why it is not a valid overriding and overloading also.
I am confuse with why java does not allow to change returntype. why return types also needs to be same
Because:
class Parent {
int method() { return 1; }
}
class Child extends Parent {
float method() { return 1.0f; }
}
Parent p = new Child();
int myInt = p.method();
What does method() return? It should be an int, because Parent says it's an int. But Child returns an float. So what do you expect to happen? Should the JVM just crash?
By the way, you can change the return-type, but it has to be a subtype of the type, the overridden method returns. So you could override a method which returns a Parent and use Child as return-type.
You can change the return type when you override the method: it just has to be overridden with a covariant type.
For example, if you define an interface like:
interface Foo {
Object foo();
}
then it is fine to implement it thus:
class Bar implements Foo {
#Override public String foo() {
return "";
}
}
because all implementations of Foo.foo() must return an Object, and all Strings are Objects.
However, you couldn't do it the other way round: if the return type of Foo.foo() were String, you couldn't implement it to return an Object, because callers of the method need to be able to invoke String's methods on that instance. For instance:
void test(Foo instance) {
System.out.println(instance.foo().length());
}
This wouldn't work at runtime if an Object were returned, as there is no length() method on an Object. (But more specifically, it must be the String.length() method, not just any length method: Java does not support duck typing). The compiler can detect this mismatch, and so it stops you doing it.
There are no types covariant with int (or any primitive type, for that matter), so you have to return an int when you override a method which returns int.
The theoretical reason why this is allowable is the Liskov Substitution Principle, which can be paraphrased as "subtype methods can be more general in the parameters they accept, and more specific in the types they return".
Java doesn't allow more general parameter types to be used, however, because of the way it resolves method overloads.
As illustrated here (emphasis my own)
The ability of a subclass to override a method allows a class to
inherit from a superclass whose behavior is "close enough" and then to
modify behavior as needed. The overriding method has the same name,
number and type of parameters, and return type as the method that it
overrides. An overriding method can also return a subtype of the type
returned by the overridden method. This subtype is called a covariant
return type.
If the return type is not the same, it will break things for other classes which could use polymorphism to detect the type of the class at runtime.
Basically, Java considers this (very correctly, I think ...) to be a nasty-bug(!) that it just helpfully caught for you at compile time.
The essential idea behind descendent-classes and overrides is that callers need not be concerned as to which “flavor” of a particular class-instance they might be dealing with, as long as it is known that it is an instance of that class or one of its descendants. The compiler can also generate reliable code, because although the underlying implementation of a particular class might vary, the prototype does not: each instance will have the same methods, a-n-d, will return the same data types.
If you need to special-case return a different data type, you should define a custom method to do so. This will also(!) be important for the various Programmers Who Will Follow You. (“Too bad about that bread-truck ...” etc.) If your code does something different, it should very-noticeably look different in the application source-code!
Remember: if Java actually allowed you to do this sort of thing, you might unwittingly introduce nas-s-s-s-ssty bugs in any piece of existing, “debugged,” code, anywhere(!) in your undoubtedly-vast application, that happened to stumble-upon an instance of “your special-case.”

Java equivalent of Objective-C instancetype?

In Objective-C, instancetype can be used as the return type of methods that return an instance of the class they are called on (or a subclass of that class).
What is the equivalent of instancetype in Java?
The closest to thing is to use generics
interface Base<B extends Base<B>> {
// do something and return this.
B append(String s);
}
interface SubBase<B extends SubBase<B>> extends Base<SubBase<B>> {
// append returns a SubBase<B>
}
class MyClass implements SubBase<MyClass> {
public MyClass append(String s) {
// do something
return this;
}
}
It's not so elegant, but it works.
If you mean something like this:
class Vehicle {
instancetype doNothing() {return this;}
}
class Car extends Vehicle {}
Car c = new Car().doNothing(); // no compile errors here
There is no equivalent.
One workaround that's sometimes used is to pass the type as a generic parameter:
class Vehicle<instancetype> {
instancetype doNothing() {return this;}
}
class Car extends Vehicle<Car> {}
Car c = new Car().doNothing(); // works
but then you can't use the type Vehicle without getting warnings everywhere (it has to be Vehicle<?>).
I'm no Javaist but likely there is no equivalent, because Java needs it only rarely. (And Objective-C do so, too.)
Please note that in Objective-C you do not need it most of the time, too. This is, because the compiler infers the "real" return type from the receiver, even it is declared id. This applies to -init…, +alloc…, -new…:
To determine whether a method has an inferred related result type, the first word in the camel-case selector (e.g., “init” in “initWithObjects”) is considered, and the method will have a related result type if its return type is compatible with the type of its class and if:
the first word is “alloc” or “new”, and the method is a class method, or
the first word is “autorelease”, “init”, “retain”, or “self”, and the method is an instance method.
In Java this is inferred for the new operator, too. The constructors does not have any return type, so it does not need to be inferred.
Up to here: No need for an (explicit) keyword in Java or Objective-C.
In some cases you have additional methods returning a new instance of the receivers class. Cloning/copying is such a case. In Java you have to type cast the result. In Objective-C you can use instancetype to make code easier to read. (BTW: NSObject's -copy has id as return type, not instancetype. But again usually this is no problem, because you typically assign the return value to a typed reference.)
So the short conclusion: In both Java and Objective-C the return type can be and is inferred by the compiler for most of the use cases. In rare use cases you have to explicitly cast in Java.

Polymorphism and method overloading

I have a quick and straighforward question:
I have this simple class:
public class A
{
public void m(Object o)
{
System.out.println("m with Object called");
}
public void m(Number n)
{
System.out.println("m with Number called");
}
public static void main(String[] args)
{
A a = new A();
// why will m(Number) be called?
a.m(null);
}
}
UPDATE: actually is method with Number actually being called. Sorry about the confusion.
If I call a.m(null) it calls method with Number parameter.
My question is: why is this? where in the java language specification is this specified?
First of all, it actually calls m(Number).
It happens because both methods are applicable, but m(Number) is the most specific method, since any argument of m(Number) can be passed to m(Object), but not vice versa.
If you replace m(Object) by m(String) (or add another method such as m(Date)), compiler would report ambiguity, since the most specific method can't be identified.
See the section Choosing the Most Specific Method in the Java Specification.
This is not polymorphism or overriding. This is method overloading.
I tested this and specific method is being called (not the m(Object)) and according to the spec the specific method is always called. Which overload will get selected for null in Java?
another related question for you to think about:
public static void main(String[] args)
{
A a = new A();
Object n = new Integer(1);
a.m(n); // which method will be called?
}
My 2 cents. Method with Number argument is the one that is called, Because Number extends Object. I had a similar situation in the past, I did override a method and put Component instead of JComponent (by mistake). It took me one week to find out the reason why my method was never called. I figure it out, that if there are some inheritance relationship between the overloaded methods, the JVM matches first the deeper one in the class hierarchy.
Object is the default type in Java. If you refactor your m(Object o) method to m(String o) you'll have a compile time error saying that the call m(null) is ambiguous because Java cannot determine which class between String and Number defaults to null
Other than that, between m(Object o) and m(Number o), calling m(null) will call m(Number o) because it's the most specialized method. You would need to cast null into an Object (or anything not an instance of Number) otherwise.
a.m((String) null);

Categories