Can a method in sub class overloading a method in super class? - java

Java code:
class P {
public void hello() {}
}
class C extends P {
public void hello(String s) {}
}
My question is: Is the hello in class C overloading the one with same name in super class P?
My friend says they are not because the are not in the same class.

Taking a more formal approach, the Java Language Specification for Java 7 states:
If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but signatures that are not override-equivalent, then the method name is said to be overloaded.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.9
I would point your friend to this link.
So, in short, in your example, the hello method is indeed overloaded.

Simple Explanation:
I think this question arises because at times we hear the following,
"Method overloading is performed within class.
Method overriding occurs in two classes that have inheritance relationship."
The above statement is correct. But your friend is wrong. why?
Because when you extend a class, the subclass have all the methods defined by superclass. It is as if all the methods of superclass have been implemented by the subclass. That means the hello() method has been implemented by the class C as well. Now, you added a method in class C with different parameter (hello(String s)). That means, class C has two methods in all with same name but different parameters and that is "overloading".
Hope it is crystal clear.

Overloading can happen in same class as well as parent-child class relationship whereas overriding happens only in an inheritance relationship.

Yes, your friend is wrong because he thinks only of the concept of overriding.
But here hello(), and hello(String s) are different by there parameters so it's overloading not overriding.

Source of confusion: Your friend would be right if speaking about C++ not Java. In C++, function overloading can only occur between members of the same class. Whereas in Java, overloading can occur, in addition to that, across two classes with inheritance relationship.

Yes it is overloading, This overloading is happening in case of the class 'C' which is extending P and hence having two methods with the same name but different parameters leading to overloading of method hello() in Class C. However Class P is only able to access one of the methods which is present in its own definition.

Long story short, an instance of C will have both the hello() and the hello(String s) methods available. An instance of P will only have the hello method available.
This is indeed overloading, as you have two methods of the same name taking different parameters.
However, it is not overriding, because overriding is having a method declared in a subclass with the same name and same parameters as a method in a superclass.
E.g. if you had
class C extends P {
public void hello() {}
}
it would be overriding the hello() method declared in P. When invoking new C().hello() in that case, you would invoke the implementation of the hello() method declared in class C.

It is a valid question since usually, overloading is explained using two methods with the same name (but different parameters) in the same class.
I would argue that yes, the method hello in C is overloading P's hello method because of the "is a" relation.
The "is a" relation states that since C subclasses P, it is also an instance of P ("C is a P"). Hence C has 2 overloaded hello-methods.

Good question!!!In sub class if method name | parameter type | list is changed then sub class method will not be considered as overriding it is considered as overloading method
Example :
class A{
void m1(int a){}
}
class B extends A{
void m1(float f)
{}
}
In above program m1 method is a overloaded method.

Yes we can overload the super class method in sub class like as bellow:
public class OverLoading {
public static void main(String[] args) {
B b = new B();
b.display();
b.display(4);
}
}
class A {
public void display() {
System.out.println("A class display method");
}
}
class B extends A {
public void display() {
System.out.println("class B subclass");
}
public void display(int a) { //Overloading in subclass
System.out.println("class B subclass with overloading");
}
}
Output:
class B subclass
class B subclass with overloading

Depends on the class. From class P's perspective (if the reference is P, the object can be of C) it is not. If you write something like: P p = new C(); there is no overloading because you cannot call p.hello("foo").
From class C's perspective it is overloaded because if you write C c = new C(); it has two methods with same name and different signatures.

This is a good question and the answer is a bit tricky.
Well, it's true that you can overload an inherited method from a parent class into a subclass. However, and here's the interesting part, the actual behavior depends on the reference variable type.
Let's consider the following example:
public class OverLoadingTest {
public static void main(String[] args) {
ChildClass cc = new ChildClass();
SuperClass sc = cc;
sc.method("lol");
cc.method("lol");
}
static class SuperClass {
public void method(Object o) {
System.out.println("SuperClass called.");
}
}
static class ChildClass extends SuperClass {
public void method(String s) {
System.out.println("ChildClass called.");
}
}
}
So, we have a class extending another and with a method that overloads a method from the parent.
It's easy to guess that if you have an instance of ChildClass, the two methods are overloaded, and overloading resolution takes place as it normally does.
However, let's consider creating an instance of ChildClass and assigning it to a reference variable of type SuperClass. Is the overloading thing still standing?
If you execute this program you will get this outptut:
SuperClass called.
ChildClass called.
The output clearly indicates that there's no overloading here in this case. This however can be altered by overriding the original method.
static class ChildClass extends SuperClass {
public void method(String s) {
System.out.println("ChildClass called.");
}
public void method(Object o) {
System.out.println("ChildClass called.");
}
}
Now, if you run the program again, you get this output:
ChildClass called.
ChildClass called.
Explanation
Now, why is JVM behaving that way? Why can't it see the overloading method as we're using an instance of the child class?
This takes us to how does JVM call a method. The JVM sees that you're referring to the object with a reference of type SuperClass, so, it can only use the methods that are related to that type, with the only exception is overriden methods. And since method(String) isn't overriding, we have method(Object) of the parent, hence, it's the one chosen for execution.
We then override the method to break this rule, and this is how the JVM called ChildClass.method(Object) even if the reference variable is of a parent class.

Overloading is when you have two methods that have the same name but different signatures (Your case).
Side note: Overriding is when you have two methods that have exactly the same signature and name and the parent class.

Related

Overloading in inheritance

So I came across this concept of overloading resolution while studying Dynamic programming but I am having trouble understanding this. The statement goes like this-
"If the compiler cannot find any method with matching parameter type or if multiple methods all match after applying conversions(casts) the compiler reports an error"
I tried verifying the statement with help of an example and it goes like following-
public class OverloadingResolution{
public static void main(String[] args){
ClassB b= new ClassB();
b.check(3);
ClassB c=new ClassC();
c.check(3)
}
}
class ClassA{
public void check(float a){
System.out.println("Inside ClassA----> value of a is"+a);
}
}
class ClassB extends ClassA{
public void check(float a){
System.out.println("Inside ClassB----> value of a is"+a);
}
}
class ClassC extends ClassB{
public void check(short a){
System.out.println("Inside ClassC----> value of a is"+a);
}
}
The outcome was:
Inside ClassB value--->value of a is 3.0
Inside ClassB value--->value of a is 3.0
My doubt is I expected a compile time error as ClassB b= new ClassB();, since b has multiple methods with matching parameters.
The output is correct as there is no method overriding being performed in class C, class C does not overrides the check() method of class B, check method in class C is treated as a separate method of class C.
Note:- you are performing Method Overriding in the code and not Method Overloading, Method Overloading can be done in single class. Method overloading means same method name same class but different parameters in method . In Method Overriding there will be more than one class.
RULES FOR METHOD OVERRIDING :
1.The method must have the same name as in the parent class
2.The method must have the same parameter as in the parent class.
3.There must be an IS-A relationship (inheritance).
According to you : "If the compiler cannot find any method with matching parameter type" -> compiler finds the method check() in class B so it is not giving compile time error.
Please refer to Overloading and Overriding

Is it possible for a superclass object to refer a subclass member method which is not inherited?

In dynamic method binding a superclass reference can only call a subclass method which is inherited and overrode by it. However, the otherwise can be implemented.
abstract class in
{
abstract void print();
}
class a extends in
{
String name=this.getClass().getSimpleName();
void show()
{
System.out.println("class "+name);
}
void print()
{
show();
}
}
class Main
{
public static void main(String args[])
{
in x;
x = new a();
x.print();
}
}
Here, it prints successfully
class a
Also getClass() returns the subclass name instead of superclass name as this refers to the superclass object in main method.
A parent object reference is just constrained by the methods that it has in its class definition. If those methods are overridden by subclass, and at run time, if the actual object referred by the parent reference is of subclass type, then that overridden method is invoked. It doesn't matter if the overridden method invokes methods that are not originally present in the parent class or accesses the variables that are not present in the parent class.
This is what polymorphism is all about. It is by design meant to be this way as it makes program extension easier in case if we have different specific inheritance hierarchies where the parent class need not know the exact implementation of certain methods and can make things implemented by the subclasses as some sort of contract.
Future is unknown A developer writing a class A.java today can never predict in future the names or signatures of the methods which any other developer may include in his class extending A.java. Also such classes may be numerous with each having separate methods.
Base class should never be coupled with its sub classes. It must not care about how the sub classes are implemented.
Although it is not recommended but still if you wish to invoke the method defined in one of the sub class you may do it by typecasting like below.
public class Parent {
public class someMethod(){
if( this instanceof Child1){
((Child1)this).someAdditionalMethod();
}
}
}
public class Child1 extends Parent{
public class someAdditionalMethod(){
}
}

Java Interfaces and inheritance

I have a very basic doubt about Java Interfaces and inheritance.
Suppose I have two classes A and B and one interface C with following definitions
interface C{
public void check();
}
class A implements C{
public void check(){
System.out.println("A");
}
}
class B extends A implements C{
// Is the following method overriding the method from class A or implementing the method from C?
public void check(){
System.out.println("B");
}
}
I am confused that whether it is over-riding or implementation of check() method in class B?
It does both, they are not mutually exclusive. The purpose of an interface is to define a method signature that should be available inside the implementing class.
You should annotate the method with #Override though, it's just good form because it makes clear that it comes from a baseclass and it'll guard you against accidental typos.
As #Jeroen Vannevel and #EJP have mentioned above it's both overriding and implementing.
In order to understand this I think you need to see it in the context of compile/run time.
You have the following possible scenarios:
C c = new B();
c.check();
At compile-time you see C#check() (you can use your IDE to get you where c.check() points to) at runtime you see the overridden B#check()
A a = new B();
a.check();
At compile-time you see A#check() (you can use your IDE to get you where c.check() points to) at runtime you see the overridden B#check()
B b = new B();
b.check();
At compile-time you see B#check() (you can use your IDE to get you where c.check() points to) at runtime you see the overridden B#check()
If alternatively you are passing the method call directly in a method:
someMethod(new B().check())
then this equates the last of the above scenarios
It is both over-riding and implementing.
In your example:
class B extends A implements C{
// Is the following method overriding the method from class A or implementing the method from C?
public void check(){
System.out.println("B");
}
}
You are defining the check method in interface C as:
public void check(){
System.out.println("B");
You are allowed to do this as interfaces don't contain the definition of the method in the interface when they are created and can thus be used over and over again for things which are similar enough to use the same method with a few tweaks.

Super keyword in Java, interesting behavior, please explain

Lets say that we have the following code:
class A {
public void doLogic() {
System.out.println("doLogic from A");
}
}
class B extends A {
#Override
public void doLogic() {
System.out.println("doLogic from B");
}
public void doDifferentLogic() {
System.out.println("doDifferentLogic from B");
super.doLogic();
}
}
class C extends B {
#Override
public void doLogic() {
System.out.println("doLogic from C");
}
}
public class Test {
public static void main(String[] args) {
C c = new C();
c.doDifferentLogic();
}
}
When we execute this code the expected behavior is the following:
Since c holds a reference to object of class C, when you invoke the c.doDifferentLogic() method the JVM searches for the method in the C class and since it is not found it starts looking at the inheritance tree. As expected the doDifferentLogic() method is found in the super class and executed. However the construct super.doLogic() is expected to look from the current reference "Point of View", which is of type C. So the super of C should B, but instead the method from the top class A is invoked.
If you remove the super keyword, or replace it with the this keyword (which is the same as "this" is implicit), you get the expected polymorphic behavior and the doLogic() from C class is invoked.
So my question is:
Should call to super.doLogic() be this.super.doLogic()(2), instead of static.super.doLogic()(1) ?
Both are invalid constructs, they are here just to try to explain myself better.
(1)or in other words - from the reference to the current object c , get the superclass of the current object and invoke the doLogic() method instead of
(2)from this class get the superclass and invoke its doLogic() method ?
In Java, the super keyword always refers to the superclass of the type in which the keyword is used, not the superclass of the dynamic type of the object on which the method is invoked. In other words, super is resolved statically, not dynamically. This means that in the context of class B, the super keyword always refers to class A, regardless of whether the B method is executed using a C object as the receiver. To the best of my knowledge, there isn't a way to dynamically determine the superclass type and use its methods without using reflection.
Hope this helps!
Here is where the JLS defines this specifically:
If the form is super . NonWildTypeArgumentsopt Identifier, then the name of the method is the Identifier and the class to be searched is the superclass of the class whose declaration contains the method invocation.
So Java considers super as referring to the superclass of the class enclosing the super.method call, not the actual run time type.
Whenever the super.doLogic() from classB is executed, it will always refer to the doLogic() method of the super class of classB which in this case would be classA. This is the desired behavior so that control does not keep passing between classes within the same method. This is the concept of a class context. Once you are in the context of a class, you will have to follow the rules established by that class and not keep passing control between different contexts.

Why doesn't Java allow hiding static methods by instance methods?

As shown in http://docs.oracle.com/javase/tutorial/java/IandI/override.html, Java does allow
Overriding an instance method by an instance method and
Hiding a static method by a static method
My question is why Java doesn't allow hiding a static superclass method by an instance method. This could be done like this:
class Base {
static void foo () {}
}
class Derived extends Base {
void foo () {}
void access () {
foo ();
Base.foo ();
}
}
I don't see any particular issue with the above approach - it is only as "messy/complex" as the (allowed) hiding of statics already is.
I suspect it is to avoid confusion with dealing with the base class. In fact I imagine the designers didn't see an obvious way this should behave.
class Base {
static void foo () {}
}
class Derived extends Base {
void foo () {} // say this compiled
}
Base b = new Derived()
b.foo(); // should the static or the virtual method be called?
Should b.foo() call Base.foo() or should it potentially call Derived.foo()?
Simple answer: that would be the mess.
Concrete answer: what to call in that case Derived.foo()? Base.foo() can't be called as it's hidden (as per you), Derived.foo() can't be called as it's not static.
Because, one are like Bananas and the other ones are Apples.
Explaination:
Static Methods are created when reading the Class-Structure
Methods are created when a object of a class is created.
Example:
Foo.bar();
is something different than
new Foo().bar();
Guess which one is called?
Foo f = new Foo();
f.bar();
Another to add here is:
1. Static methods belong at the class level. So u cannot override method in the derived class.
as simple its called hiding. :)
2. Instance methods belong to the objects, so objects are overrided. So we can override in the derived class.
Above other comments give a good example have a look into it..
Regards
Punith

Categories

Resources