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().
Related
Here is my question. I have a super class with an abstract method in it.
public abstract class Base{
public abstract Boolean foo();
}
public class sub extends Base{
#Override
public Boolean foo(){
System.out.printLn("This is foo in the sub class!");
}
}
so When I go to the main and try this code
Base b = new sub();
b.foo();
I got no error and message shows on my screen. My assumption is the compiler looks at the b object and sees it as a Base object then it goes to the foo from the Base object and sees there is no implementation afterwards it checks out the foo from the child and then it sees the method foo is implemented there so it shows the message. Am I right?
Compiler does not see if the method is implemented by subclass or not. It only checks whether method called by the a particular class type reference is present in the class itself or not. At runtime it decides which method to call means Base class version or Subclass version.
So you are only right upto "My assumption is the compiler looks at the b object and sees it as a Base object then it goes to the foo from the Base" statement.
Compiler does not do so much of processing. Here in your case
You have created the reference variable as of your superclass which will hold the object of child class.
Now when you are calling the method it is directly calling the method present in your subclass based on your object type.
I am adding you code with my comments for your reference.
1) Abstract class having only method declaration
public abstract class Base {
public abstract Boolean foo(); //method declaration
}
2) Child class extending your parent class where you have to implement the method,If you are declaring this class as concrete class.
public class sub extends Base {
#Override
public Boolean foo() {
System.out.printLn("This is foo in the sub class!");
}
}
3) Here you have declared reference variable of your parent type that is storing the object of you child class
Base b = new sub();
4) when this line will get executed compiler will check, what is the type of object and call that method on the basis of object type.It will not invoke methods on the type of reference variable.
b.foo();
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.
The first question is inside the code. The second question is why static methods can't be overridden to be non-static methods? The third is why can't static and abstract go together?
class A {
public void display() {
System.out.println("Display of Class A called");
}
}
class B extends A {
public void display() {
System.out.println("Display of Class B called");
}
}
class C extends B {
public void display() {
System.out.println("Display of Class C called");
super.display(); // calls B's Display
// Is there a way to call A's display() from here?
}
}
[B] // Is there a way to call A's Display from here???[/B]
No, you can't go two steps up in the class hierarchy. You could implement and call a method in B which would invoke the A implementation.
why static methods can't be overridden to be non-static methods
static methods are associated with a class. Polymorphism (and thus overriding) is a concept that applies to objects and therefore does not apply to them.
why can't static and abstract go together
For the same reason given above. An abstract method is a method that should be implemented in a sub class because the sub class inherited it. Since a sub class does not inherit a static method, a static method cannot be abstract.
First question: no you can't call the bass class's bass class directly, since in class C's view, it has no idea that class B has a bass class and it's class A. All that's know by C is that it has a base class, and it's B.
Second question: static methods are simply a neat way to organize global methods. There's no inheritance. You just put that method to a class so when you write code to call it, you know where to locate it.
Third question: abstract means "this is what the class to do, here are some basic functionality, but I cannot finish this; inherit me and finish whatever is left to get it working". As mentioned earlier, static method is just a way to put methods that "stand by themselves", requires no initialization and no context. The two does not go together.
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.
Given the following source and ouput:
Source:
public class A
{
public void foo()
{
bar();
}
public void bar()
{
System.out.println ("in A's bar() method");
}
}
public class B extends A
{
#Override
public void foo()
{
super.foo();
// Do some specialized B stuff
}
#Override
public void bar()
{
System.out.println ("in B's bar() method");
}
}
public class Main
{
public static void main (String... args)
{
B b = new B();
b.foo();
}
}
Output:
in B's bar() method
Can someone please explain to me how the JVM is smart enough to polymorphically call B's (as opposed to A's) bar() method in this situation? I'd like to know what kind of dynamic dispatch magic is going on behind the scenes here.
Update: In case I wasn't clear enough, I know basically WHAT is happening, I'm looking for specific details on HOW the JVM makes it happen under the hood. The answers so far are too simplistic.
Update 2: Maybe I wasn't clear enough. When b.foo() is called, then super.foo() is called, then bar() is called in class A's foo(). How does the bar() that is called when specifically invoking super.foo() not call class A's bar() method, since the super keyword explicitly specifies class A? What steps does the JVM have to go through to sort this out?
Also, does this mean it's a bad idea in general to call public methods from within their own class since they can be overridden in this way?
Java uses the object's type when invoking the methods.
A b = new B();
b.foo();
Let's say you used above code.
Here what will happen is you are creating an object of type B and assign it to a reference of type A. Since the object type is B, you'll invoke the method in class B.
Even if the constructor or method you're currently in is defined in a super-class, the object doesn't change type. It will still be an object of type B. This can be demonstrated by using the this keyword.
this refers to the current object. That is not the same as the class defining the current method or constructor.
Try typing the following into A's constructor or in the foo() method:
System.out.println(this.getClass());
The function call sequence is (from eclipse debug view):
1. B.foo() // super.foo()
2. B(A).foo() // bar()
3. B.bar()
After the thread calls super.foo(), the JVM will check if there's any implementation in B (since we still hold B.class in the stack), if there is, JVM will call it.
This feature is guaranteed by JVM implementation. It is not smart, it just be designed this way, just like C++'s virtual methods.
Hope it helps.