Code:
class A{
A() {
test();
}
void test(){
System.out.println("from A");
}
}
class B extends A {
void test() {
System.out.println("from B");
}
}
class C {
public static void main(String args []){
A a = new B();
a.test();
}
}
Output:
from B
from B
Why is it getting printed that way ?
This is extremely bad code. What's happening is that void test() is being overridden in the child class B.
new B(); creates an instance of class B. The fact that you reference cast it to A is not relevant here. But even though the child class has not yet been constructed, the Java runtime calls a method in that child class from the constructor of the parent class A.
Use this (anti)pattern with extreme caution! (Note that in C++ you get undefined behaviour).
When you call a polymorphic method at runtime, Java uses a special data structure to decide a method of which class needs to be called. This structure is set up at the time the object is constructed, before any of the user-supplied constructor and initializer code get executed.
When you create A a = new B(), the data structure that says "when test() is called, you need to call A.test() or B.test()" is prepared before the constructor of A is entered. Since this structure is prepared for the B class, it points to B.test(), even though the calling code is inside A's constructor. That is why you see "from B" printed twice.
Note, however, that although technically your code will do what you want, logically it is a very poor decision. The reason why this code is bad has to do with the initialization sequence: imagine a test() method that relies on private fields of B being initialized in the constructor, like this:
class B extends A {
private final String greeting;
public B() {
greeting = "Hello";
}
void test() {
System.out.println(greeting + " from B");
}
}
One would expect to see "Hello from B" being printed. However, you would see it only in the second call: at the time the first call is made, greeting is still null.
That is why you should avoid calling method overrides from inside a constructor: it breaks method's assumption that the object has been fully initialized, sometimes with rather unfortunate consequences.
During runtime, the method is invoked from actual instance object. i.e B.
A a = new B();
a.test();
In the above code, You have instantiated Object B, not A. You have just assigned the reference variable of type A. Internally, it is referring only an instance of B. During compilation, it just checks whether the method is actually present in A reference and allow it to compile. During Runtime, the method is actually invoked on the real object i.e. B referred by the reference A
This is one of the most important concepts of Object Oriented polymorphism.
By extending A with class B you are creating a more specific implementation of it, overriding some of its methods with new ones (such as your test() method) and potentially adding things to it (members and methods).
Whenever you override a class, the methods of the subclass will be invoked, irrespective of which class they are 'acting' to be.
When you cast an object to another class (like in your case B to A) you are just saying I want to see it as a reference of type A. This is useful for methods that accept objects of type A as parameter.
Consider this example:
Employee (super class) which has method float computeSalary()
Technician extends Employee which overrides method float computeSalary()
Manager extends Employee which overrides method float computeSalary()
The SalaryGenerator class has a method generateMonthlyPay(Employee e) that calls the computeSalary() of the Employee superclass, but the specific sub-class method will be invoked, because each have a different way of calculating their monthly salary.
Although the reference type is A, it's object type is B which means that it is pointing to the implementation in B. Hence, from B gets printed.
When the object a is created using,
A a = new B()
the constructor gets invoked from base class to derived class.. here the base class constructor calls test(), but this calls test() in derived class because of the over riding concept.
So you get " from B" initially.
Again a.test() calls the over rided derived class test(). So again from B is printed
Related
When I call the super class method ma() it is printing the address of B.My question is in this program what is the function of this keyword. Why using this keyword inside print statement not giving syntax error rather it gives error for the super keyword.why it will print reference of B only why not A class.
class A
{
public void ma()
{
System.out.print(this); //printing address of B why?
}
}
class B extends A
{
public void mb()
{
super.ma(); //calling super class method
}
public static void main(String[] args)
{
A re=new B(); //creating object for class B
re.mb(); //calling method mb() of class B
}
}
this is a reference to the current object — the object whose method or constructor is being called
ma() method of class A is indirectly invoked using instance of class B.
A re=new B(); //creating object for class B
re.mb();
this always refer to the object on which the method is called. Always.
Look closely at your code, have you ever created a new instance of A? No. Then no identifier can refer to an A object, so logically your code can never output the address of an A object.
I think you misunderstood the meaning of super. It just means "to call the super class implementation of this method", not "call this method by creating an instance of the super class". Therefore, super will only make a difference if your derived class has a different implementation of the method. Here, it doesn't.
Even though you are calling the super implementation, the object on which you call this method does not change. It is still this.
Given the code snippet:
class A {
public String foo() {
}
}
class B extends A {
public String foo() {
super.foo();
}
}
What happens when we invoke:
B b = new B();
b.foo();
Is the A object internally created, just to call A.foo()?
No. You don't create any other object.
When you extend a class and instantiate the child you have already created an object that is supertype instance plus your extended stuff.
Although you don't actually create two separate objects, you create one that is both (B is A++) which is also known as polymorphism (you have an object that can execute supertype methods).
the super.method() syntax disables the regular dynamic method dispatch mechanism and explicitly calls the method defined for this object's superclass, passing in the same this reference. No instantiation is involved.
A instance is created once new B(); is called. Remember, that derived classes are in is-a relation with parent class. Here, one can say, that B is-a A.
As per my understanding, when we up cast the child object to the reference of parent class, the child object loses it specific properties pertaining to child class. However, it still recognizes overridden methods and variables.
My question is why the output shows the result from child class in case of over ridden method and result from parent class in case of overridden variables. Why is such difference in behavior among methods and variables
class A
{
int a = 2;
public void show()
{
System.out.println("Inside A");
}
}
class B extends A
{
int a = 555;
void show()
{
System.out.println("Inside B");
}
}
class Demo
{
public static void main(String[] args)
{
A obj = new B();
System.out.println(obj.a); // prints 2.
obj.show(); // prints Inside B
}
}
Because your understanding is wrong. Java objects behave pretty much like real objects. Just because you refer to a Child as a Human doesn't change anything to how the child moves, cries and plays. It's still a Child.
That's the whole point of polymorphism: you can refer to an object without knowing its concrete type, and it will behave as defined in its concrete type definition.
Note that polyporphism and overriding only applies to methods, and not fields. Fields are never resolved in a polymorphic way. They should not be accessed directly from the outside anyway: always through methods. That's the other main principle of OO: encapsulation.
In B, you're not overriding the field a, but introducing another field with the same name, which hides the one defined in A.
Overriding applies to methods, not fields. Having same field in subclass hides the super class field.
Since type of obj is A, the actual value a which is intialized in A gets printed
I have a question and below is my code.
class A
{
int i=10;
public void m1() {
System.out.println("I am in class A");
}
}
class B extends A
{
public void m1() {
System.out.println("I am in class B");
}
}
class main2 extends A
{
public static void main(String...a) {
A a1= new B();
a1.m1();
}
}
Now my question; it's OK to get the variable "i" of the parent class A, but the method that I am getting is also of class A. Is it getting class B's method, as it overrides class A's method?
In Java, any derived class object can be assigned to a base class variable. For instance, if you have a class named A from which you derived the class B, you can do this:
A a1 = new B();
The variable on the left is type A, but the object on the right is type B. As long as the variable on the left is a base class of B, you are allowed to do that. Being able to do assignments like that sets up what is called “polymorphic behavior”: if the B class has a method that is the same as a method in the A class, then the version of the method in the B class will be called. For instance, if both classes define a method called m1(), and you do this:
a1.m1();
the version of m1() in the B class will be called. Even though you are using an A variable type to call the method m1(), the version of m1() in the A class won’t be executed. Instead, it is the version of m1() in the B class that will be executed. The type of the object that is assigned to the A variable determines the method that is called.
So, when the compiler scans the program and sees a statement like this:
a1.m1();
it knows that a1 is of type A, but the compiler also knows that a1 can be a reference to any class derived from A. Therefore, the compiler doesn’t know what version of m1() that statement is calling. It’s not until the assignment:
A a1 = new B();
is executed that the version of m1() is determined. Since the assignment doesn’t occur until runtime, it’s not until runtime that the correct version of m1() is known. That is known as “dynamic binding” or “late binding”: it’s not until your program performs some operation at runtime that the correct version of a method can be determined. In Java, most uses of inheritance involve dynamic binding.
Yes, it calls the B implementation of m1. When you run this code, it prints
I am in class B
just as expected. (Note that you don't actually use i in any of the code you posted, so I'm not sure what the first part was about...)
Yes it will invoke B's version of method, Since the object is of class B
public class A
{ }
public class B extends A
{
public void add()
{
System.out.println("add in B");
}
}
Now here if we call add in following way hen it gives an error:
A a1 = new B;
a1.add();
But when we add the add() method in class A and then call in the similar fashion then add() method of child class is called.
i.e.
public class A
{
public void add()
{
System.out.println("add in A");
}
}
public class B extends A
{
public void add()
{
System.out.println("add in B");
}
}
call:
A a1 = new B;
a1.add();
output:
add in B
Why is it so?
at the method invocation of a1.add() the compiler checks if the method is present. But it only knows that a1 is a reference to an object of class A, which does not have that method. So the compilation fails.
In this trivial example it would probably be easy for the compiler to deduct the correct type. But in more general cases it wouldn't. And therefore this kind of logic is not part of the specs.
Because java does not know at compile time that a1 will refer to an instance of B at runtime. It only knows the declared type, so it only allows calls that work with the declared type.
When the Java compiler looks at the reference a1, it knows what methods are available. In your first example, class A does not have add() in its API. It is legal in this case to perform a cast of a1 to B like so:
((B)a1).add();
and the compiler will not complain.
You want to call a method on an object of declared type A but implement it only in a subclass B of A.
In this situation you would normally make A an abstract class and declare add() an abstract method in A.
Good answers...I had a doubt too regarding this but now I am clear :)
And one more thing ..you don't have to go into the trouble of declaring an abstract method,just make an empty method with the same name and signature in your parent class and " voila " all compilation errors are gone ;)
In your case you can add a void add(){} method like this and you wont have any problems