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.
Related
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
Kindly excuse my question as I have tried to search the difference between using super keyword vs class name to call a method from super class but am unable to find an answer.
My question is I am trying to learn Java as a study course and am using an example from the link: http://www.javatpoint.com/super-keyword using Example # 3 and here is the code I have written:
I have created a super class named Vehicle
public class Vehicle {
Vehicle() {
System.out.println("Vehicle constructor created");
}
public void speed() {
int a = 20;
System.out.println(a);
}
}
and then created a sub class named Bike with the following code:
public class Bike extends Vehicle {
int speed;
Bike(int speed1) {
this.speed = speed1;
System.out.println(speed1);
super.speed();
}
public static void main(String args[]) {
Bike b = new Bike(10);
}
}
In the sub class under Bike constructor I am using super.speed() to call speed method from super (Vehicle) class. Now if I change this line to Vehicle.speed() I get an error stating that I need to make my speed method as static.
I do not want to make my method as static and want to know about the difference between both of them.
Cheers,
Calling a method using class name directly means that you want to call a static method, which is not related to any object of the class but the class it self.
That is why the compiler tells you that the method must be static.
As for your question, when you create an object of a child class (Bike class in this example) an object of its parent is always created, on the base of which the particular child object is created.
Its like, when ever you create a Bike, a backing Vehicle is always created, based on which the Bike is created. Otherwise the Bike wouldn't be a Vehicle.
So calling a method by super means, you're telling the compiler to call this method on the class which was used as base(parent) for making this Bike class, from which I'm calling this method.
when you're calling the method by class name, you're telling the compiler to call this method of Vehicle class which is not related to any Vehicle object/instance (and obviously not related to any child (e.g. Bike object or instance as well)
Methods that aren't static can only be called on a specific instance of an object. That is why calling Vehicle.speed() would only work if the speed method were static. The reason you can call super.speed() is because in the constructor, you have already constructed the vehicle object, and are basically calling the method on the object you are constructing.
For the above example, I would say that calling super.speed() is the best approach.
Also, as you haven't overriden the super implementation of the speed method, you can just as easily call this.speed() or speed(). That approach would mean that if you ever decided that the Bike needs different functionality in the speed method, your specific implementation would be called as opposed to the default.
The two constructs are not equivalent.
When calling Vehicle.speed() the compiler is looking for a static method named speed() in the class named Vehicle. A static method doesn't belong to any instance of the class. You cannot use any instance variable inside a static method. You haven't defined a static method named speed() in your Vehicle class and therefore there's no such thing as Vehicle.speed(). Hence, you get a compilation error.
When calling super.speed(), you don't look for a static method as in the previous case: The actual method that is going to be called when using the super syntax is an instance method (named speed() in your case) defined in the superclass of the current object. That is, super.speed() is the instance method defined in the super class of the current object (unlike this.speed() which is the instance method named speed() defined in the actual class of the current object). In other words, it is going to call the method speed() defined in the class Vehicle, but the this parameter is going to be the one referenced by b, the current object.
You need instance to calls instance(non-static) method.
super is parent class's instance. Simply put class name is not an instance(it' a static context for entire class).
[super is parent class's instance ?]
Jon skeet said no such thing as a "parent instance", but i doubt the term of instance.
super's variable is initialized first and then the turns of child to decide whether share the same variable/method(i.e. return this.i; in this kind of method will return super.i, not this.i, when call by child) or override it.
import java.util.Random;
class Love {
int i = 1;
int hole() {
return this.i;
}
}
class Main extends Love {
void wrapper() {
System.out.println(super.i); //1
System.out.println(this.i); //2
super.i = new Random().nextInt(50) + 2; //to avoid compiler pre-optimizing hard coded return value in hole(), so we set again.
System.out.println(super.i); //23
i = 3; //2nd attempt override
this.i = 3; //3rd attempt override
System.out.println(hole()); //23, super "instance" keep its own version of this.i
}
int i = 2; //1st attempt oveeride
public static void main(String[] args) {
new Main().wrapper();
}
}
So it's obvious when child override, super still keep its own version, so IMHO super can roughly treat like a parent instance, just the difference with normal instance are it's a keyword with some restriction of usage (e.g. super.super.i is not allow, direct print super not allow). One more difference is the variable value will sync in each instance due to child might share it as mentioned above.
You can try to print super.variable_name inside static method, it will output super is a non-static variable:
$ javac Bike.java
Bike.java:132: error: non-static variable super cannot be referenced from a static context
System.out.println(super.dummy);
^
Bike.java:132: error: cannot find symbol
System.out.println(super.dummy);
^
symbol: variable dummy
2 errors
$
So it's make sense super as a non-static variable can access non-static method speed() in your example.
If you want to use method directly with class name then you have to specify method as static
public static void speed() {
int a = 20;
System.out.println(a);
}
or
you can create an object of class Vehicle and access speed method in your subsclass like this
Bike(int speed1) {
this.speed = speed1;
System.out.println(speed1);
Vehicle vehicle = new Vehicle();
vehicle.speed();
}
hi super is a keyword which is used to access the super class methods in sub class.
This super keyword is used mainly when methods are overridden.
example
class A
{
method m()
}
class B extends A
{
method m()
method m1()
{
super.m()
}
}
class C
{
public static void main(String args[])
{
B b = new B();
b.m() // calls method m() in class B
b.m1() // calls method m() in class A because method m is pointing to super class method
}
}
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.
class A {
A() {
System.out.print("A");
}
}
class B extends A {
B() {
System.out.print("B");
}
}
class C extends B {
C() {
System.out.print("C");
}
}
public class My extends C {
My(){
super();
}
public static void main(String[] args) {
My m = new My();
}
}
Question starts from one Interview Question (what happens when an object is created in Java?)
and answer is...
The constructor for the most derived class is invoked. The first
thing a constructor does is call the consctructor for its
superclasses. This process continues until the constrcutor for
java.lang.Object is called, as java.lang.Object is the base class for
all objects in java. Before the body of the constructor is executed,
all instance variable initializers and initialization blocks are
executed. Then the body of the constructor is executed. Thus, the
constructor for the base class completes first and constructor for the
most derived class completes last.
So, according to above statement, answer should be ABCC, but it showing only ABC. Although, when i'm commenting the super() in derived constructor. Then, output is ABC. Please, help me to figure out, did i misunderstand the above paragraph. ?
No, the answer is ABC
My m = new My();
The above first invokes My class, then a super call is made to its super class i.e., C class, then a super call to B class is made, then a super call to A Class, then a Super call to java.lang.Object as all objects extend java.lang.Object.
Thus the answer is ABC.
You don't really need to explicitly call super() in your My class as it'd be included by the compiler unless you call an overloaded constructor of that class like this(something).
The below code will print ABC
To invoke the constructor of the super class, the compiler will implicitly call the super() in each and every class extending the class, if you are not calling the super construcotr explicitly.
abstract class A {
public void methodA() {
System.out.println("methodA");
methodB();
showName();
}
public abstract void methodB();
public void showName() {
System.out.println("in showname base");
}
}
class B extends A {
public void methodB() {
System.out.println("methodB");
}
public void showName() {
System.out.println("in showname child");
}
}
public class SampleClass {
public static void main(String[] args) {
A a = new B();
a.methodA();
}
}
Output is :
methodA
methodB
in showname child
Question :-
Since in overriding, the object type is considered. Is it the reason behind that class B's showName() method called not of class A's? If not then whats the cause of this output order?
You created an object of type B, so all methods called on that object will be on class B. If class B does not implement some methods (like methodA), then Java tries to find a method in the parent class (A). You should read about polymorphism in object oriented languages:
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
It's easy:
A a = new B();
a.methodA();
here is known that a is object of B class, so every method that can be overriden in class B is used from class B if there is no overriding, then method from class A must be used.
Considering order:
you invoke methodA that is declared as:
public void methodA() {
System.out.println("methodA");
methodB();
showName();
}
from inside of methodA() you invoke both methodB() and showName(). They are overriden in class B, and object a is instanceof B, so that's why they (from B class) are used.
EDIT as mentioned in comment:
#Jaikrat Singh, class B is still class A (child of it, but inheritance is relation of type: IS-A ). Class B has inherited methods from A class. So it has methodA as well. So it's better to say, that methodA is also called from class B but with is default code - the same as provided in class A
While the object 'a' is declared as type A, it is instantiated as type B. Polymorphism causes the methods of the instance type to be called rather than those of the declaration type, so because it is internally of type B, the showName() method of class B is called.
When you call a.methodA(), since your object type is B, it will look for methodA first in B. Since there is no such method in B, it will look for this method in its super class, which is A. Finding methodA in class A, it will start to execute.
Executing, it will print methodA and start looking for the next called method (methodB), which is implemented in the B class, then it will print methodB.
The next called method is showName, which is implemented in both classes. Since Java will start looking for the implementation in the same class as the object type, it will find in its first attempt, which is class B.
The main rule is simple: Java will first try to find the method in the object type class (the name that goes after the new operator). If the method is not implemented there, it will start to go up through the super classes.
You have the abstract class A, and it is extended by B. Extends is equivalent to B "is a" A. For example if apple extended fruit, apple 'is a' fruit. It acts like a fruit but also does apple things that a banana wouldn't do. So B acts the same way as A, but then also can do other stuff. So in your example, your B overwrites two methods. They will be called by every B object by default. In order to access A's methods from a B, you need to use the keyword super .
It is part of polymorphism (a key point in java programming) that an object will find any methods in itself first (even if they are overwritten from a parent) and then it will climb the tree of inheritance to find a method that isn't directly in that class.
For your example:
public void methodA() {
System.out.println("methodA"); //This prints no problem.
methodB(); //This searches the "B" class for a method called "methodB" If it can't find it, it checks its parent for a "methodB"
showName();//This searches the "B" class for a method called "showName" If it can't find it, it checks its parent for a "showName"
}
The above code gets called. You know this much (from other comments you made, I'm assuming this.) Once the line methodB() gets called, your object of type B checks the entire B file for the method. It would only jump up to A for the method if it didn't exist. Then it would do the same for showName().