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
Related
bb refers Derived class, when i call show() method, but when i print bb.b - is prints Base class property .
Why is this happening?
class Base {
int b=10;
public void show() {
System.out.println("Base show() called");
}
}
class Derived extends Base {
int b=20;
public void show() {
System.out.println("Derived show() called");
}
}
public class MainClass {
public static void main(String[] args) {
Base bb = new Derived();;
bb.show();
System.out.println(bb.b);
}
}
output :
Derived show() called
10
While you declare your variable as a Base obj (i.e. Base bb = new Derived();), that does not mean your b object is no longer an instance of Derived (verify this with b instanceof Derived).
This is called hiding and is similar to what people usually do when declaring variables that might later change implementation for example private List<String> someList = new ArrayList<>();. In more technical terms: it's a way of decoupling your code from a specific implementation.
As to why b is 10 (the Base class's value) and not 20: that is because you are explicitly referring to b value in Base class (as mentioned by Timothy Truckle's answer). If you were to explicitly cast your b object back to Derived type, you will see 20 being printed instead:
System.out.println(((Derived)b).b);
You output is 10because you explicitly access variable b in class Base.
Beside the technical aspect doing so this is not OOP since it violates the most important OO principle: information hiding / encapsulation.
This is because the compiler implements special run time polymorphism for methods only. This is also called method overriding.
For variables, the value will always be from the Base class, because that is the type of bb object regardless of the class with with it is instantiated.
There is no polymorphism for fields in Java.
Variables are resolved compile-time, methods run-time. so always Base Class variables (not child’s inherited variables) will be accessed.
So whenever upcasting happens always remember
Base Class variables will be accessed.
Sub Class methods(overridden methods if overriding happened else inherited methods as it is from parent) will be called.
This is probably answered somewhere, but I have no idea what to search for. Imagine you have the following...
The superclass, Animal.java
public class Animal {
public String noise = "squeak";
public String toString() { return noise; }
}
The subclass, Lion.java
public class Lion extends Animal {
public String noise = "ROAR!!";
public String toString() { return noise; }
}
The main class, Runner.java
public class Runner {
public static void main(String[] args) {
Animal a = new Animal();
System.out.println(a);
System.out.println(a.noise);
Lion b = new Lion();
System.out.println(b);
System.out.println(b.noise);
Animal c = new Lion();
System.out.println(c);
System.out.println(c.noise);
}
}
The output is:
squeak
squeak
ROAR!!
ROAR!!
ROAR!!
squeak
Why does c.noise return squeak? What is the difference between instance method invocation and instance variables that one returns what you'd expect, and the other does not? Why does Java do this?
Thanks
Short answer:
You can override methods, but it's not possible to override fields.
Long answer:
Each class sees the methods and fields of it's own and of it's parents (except for private methods). If the child delcares a method, whose name is the same, as the name of the method in his parent class, this method becomes overridden - if this method is somehow invoked on the child instance (even from the one of the parent's methods), the brand new method will be used instead of the parent's one. Child may still call the original method of his last parent via super.method(...) call.
But the story is different when we come to the fields. If the child declares a new field, that is named exactly as the field in parent class, it will simply hide the parent's field without overriding, just like the local variable hides global one. So the child methods will simply see the child's fields, but the parent's method will continue to see parent's field, and child's field will not be visible by any means from the parent class - that's what you've got.
Child can access the field of it's parent via ((Parent)this).field.
Longer answer:
So really the way you'd do this is define Lion thus:
public class Lion extends Animal {
public Lion() {
noise = "ROAR!!";
}
}
So now for Lion instances the noise member variable of Animal has been updated to ROAR!!
Of course you'd (almost) never actually have a public mutable member on a class like that in the wild.
You can not override fields, new declaration of noise in Lion hides parent's noise attribute. do like this:
public class Lion extends Animal {
// public String noise = "ROAR!!"; // <---- Remove this line
public Lion() {
noise = "ROAR";
}
public String toString() {
return noise;
}
}
All non-static methods in java are by default "virtual functions". Unless they're marked as final (which makes the method not overridable). Java uses a virtual method table to call the correct object's method.
This is because Java talks only about method overriding. Member variables can only be shadowed in child class. So when you say c.noise it actually refers to the string variable in parent class as the c if reference type Animal.
The topics you are interested in are Dynamic Dispatch and Virtual Method Table. Basically, by design, Java allows for methods to be overridden (assuming they are non-final) and at run time the JVM will execute the appropriate implementation. This polymorphic attribute is only afforded to methods. Good OO design would dictate the fields be encapsulated anyway.
Can anybody explain me what is the reason for a sub class object is incapable of holding a super class constructor?
class Alpha
{
String getType1()
{
return "alpha";
}
}
class Beta extends Alpha
{
String getType1()
{
return "beta";
}
String acc()
{
return "acc";
}
}
public static void main(String[] args)
{
Alpha a1=new Beta();
System.out.println(a1.getType1());
}
Here the output is "beta"; but object a1 doesnt have the visibility to acc()?
Nothing surprising here:
System.out.println(a1.getType1());
You are calling a method that is defined in the super class; and overridden in the a subclass. You create an instance of the subclass; and the method that gets executed ... is the overridden version.
The fact that Beta contains another method which is not at all used in your example anyway doesn't come into play here at all. And even if getType1() would be calling acc() - that would still work. That is the essence of of polymorphism!
And just to be precise: none of the methods you have in your classes is a constructor!
i just found the answer here we need to know that when we create beta() internally it will call all its super class default constructors hence the JVM knows that there is more than one existing class but when i declare and initialze like:
Alpha a1=new Beta();
eventhough the JVM knows that beta class is existing but your restricting your access of a1 by saying it is of the type Alpha class hence it cannot access your subclass methods.
When you create a object of child class making reference to its parent class as you did, you only have visible to those methods which belongs to the parent class. but if you want to call the child method using reference of parent class then you have to declare the body of the method in parent class which you have in child class. then it will be visible and this concept is called method overriding.
If you don't need to create the object of your super class then you can declare class as abstract and then you can simply put that method as abstract keyword shown as below.
abstract class Alpha
{
String getType1()
{
return "alpha";
}
abstract String acc();
}
class Beta extends Alpha
{
String getType1()
{
return "beta";
}
#Overriding
String acc()
{
return "acc";
}
}
public static void main(String[] args)
{
Alpha a1=new Beta();
System.out.println(a1.getType1());
}
Child classes are privileged to access to default constructor of parent class until unless you have restricted it with private access modifier.
Your cases is an example of method overloading. Actual call to overloaded method is resolved at run time. Which method will be called, depends on the concrete object not type of object. Here your reference is of type Alpha but the object is of Type Beta. So method getType1() here will print beta which is correct behavior.
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
I have the following code snippet that attempts to use this and super.
class SuperClass
{
public final int x=10;
public final String s="super";
public String notOverridden()
{
return "Inside super";
}
public String overrriden()
{
return "Inside super";
}
}
final class SubClass extends SuperClass
{
private final int y=15;
private final String s="sub"; //Shadowed member.
#Override
public String overrriden()
{
return "Inside sub";
}
public void test()
{
System.out.println(super.notOverridden());
System.out.println(this.notOverridden());
System.out.println(this.overrriden());
System.out.println(super.overrriden());
System.out.println(this.s);
System.out.println(super.s);
System.out.println(this.x);
System.out.println(super.x);
System.out.println(this.y);
}
}
public final class Test
{
public static void main(String[] args)
{
SubClass subClass=new SubClass();
subClass.test();
}
}
In this simplest of Java code, the statements that redirect the output to the console inside the method test() within the class SubClass display the following output.
Inside super
Inside super
Inside sub
Inside super
sub
super
10
10
15
So, it appears that there is no difference between this and super, when they are used to access methods which are not overridden in its subclass(es) and in case of variables, when they are not shadowed in its subclass(es).
Both of them tend to point to super class members. There is however, an obvious difference, if such is not a case.
Are they same, when methods are not overridden or variables are not shadowed in respective subclasses?
So, it appears that there is no difference between this and super,
when they are used to access methods which are not overridden in
its subclass(es) and in case of variables, when they are not
shadowed in its subclass(es).
There is a difference. If you override methods in third class, and call test from it, you will see, that super still calls implementations of SuperClass. And this will call new implementations (overridden).
Addition:
this.method() usage implies the method belongs to instance of the object. So the last implementation will be used (with exception of private methods).
super.method() usage implies method of the instance, but implemented before the current class (super, or super.super etc).
Yes, they are the same. notOverridden methods and not shadowed variables are inherited by subclass.
To better understand this, knowing how object is located in memory is helpful. For example in the figure below. Assume it's an object of a subclass. The blue area is what it inherits from its parent, and the yellow area is what is defined by itself. The method has the similar design except that it uses a Vtable.
Child object has the same memory layout as parent objects, except that it needs more space to place the newly added fields. The benefit of this layout is that a pointer of parent type pointing at a subclass object still sees the parent object at the beginning.