I dont understand this inheritance functionality - java

Consider the following illegal code :-
class WrongCode{
int i;
static int i;
}
Here, the compiler says that we have duplicate fields in the same class.
Now, consider the following classes in the same file.
class Parent{
int i = 10;
}
class Child extends Parent{
static int i = 100;
}
public class Main{
public static void main(String ... aaa){
Parent ob = new Child();
System.out.println(ob.i); // This prints Parent's i
}
}
Since the actual object is of Child, shouldn't ob refer to Child's i? And if it is refering to Parent's "i", then in a way it is also having Parent's "i" in its own class along with its own static "i" which is NOT ALLOWED.
Child static i overshadows Parent i. And Parent's i is not static, so then how is it accessed directly using instance and not className?

You have instance field i in Parent class and it remain an instance field in Child class.
System.out.println(ob.i); // must be 10
Have a look at - Oracle Java Tutorial - Hiding Fields

It is important to realize here that there is no way System.out.println(ob.i); could print Child's i: it only knows that ob is of declared type Parent, not that it was instantiated with an actual Child. Thus, if Parent did not have any i, there would be a compile error. If parent has an i, this is printed.
I have seen it mentioned on SO that access of class variables via instances (i.e. ob.i being equivalent to Parent.i) should be considered a serious design flaw of Java. I agree it can be sometimes confusing. Anyway, both your parent and child could also have a non-static i and it need not be the same. The argument above should be applicable to reasoning which one would be printed in which situation.

In ob, the static int i of child is never visible since ob is of type Parent, irrespective of how it was instantiated( base class or derived class).
That's why you have the value as 10, that Parents i value.

When you access class member fields (instance variables) like ob.i. you'll get the results from the class that's known at compile time, not what is known at run time. Thats why you have value as 10 which is parents value.
For method calls they are dispatched at run time to an object of the actual class the reference points.
Regarding shadowing here is what Java lang spec says:
If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class.
A hidden field can be accessed by using a qualified name (if it is static)
language spec
You may refer "Field Declarations" section.

Actually its polymorphism and ob have access only to parent class fields and behaviuors if any...

Java lets your class have its own variables that have the same name as a variable in the parent. But it can't just let you randomly redefine parent variables, as that would cause other stuff to break. So what it does...when you have a variable obj that's declared as the parent class, even if it holds an instance of a child class, obj.i will refer to the parent class's i rather than the child's.

Related

Java instance variable resolution in Java is confusing;

I am studying for my OCA exam and came across this problem and It is very confusing.
Variable resolution always based on reference type instead of the runtime object. So if my parent and child class look like this:
class Parent {
public int x = 1;
public int getX() {
return x;
}
}
class Child extends Parent {
public int x = 2;
public int getX() {
return x;
}
}
Based on the rules (variable resolution is always based on reference type), the following code is behaving as expected:
Child c = new Child();
System.out.println(c.x); //2
System.out.println(((Parent) c).x); //1
However. if I retrieve the variables by using the getter defined in the parent and child class, then I get this:
Child c = new Child();
System.out.println(c.getX()); //2
System.out.println(((Parent) c).getX()); //2
Shouldn't it print the same as if I was to access the variable directly? why would getting the variable via getter be different than getting the variable directly?
One theory I have is this:
Since instance method resolution is based on runtime object, therefore it overrides the variable resolution rule. In other words, the compiler will resolve the getter methods to the child class since instance method resolution is based on runtime object. Am I right?
Thank you
Methods and variables behave differently. Variables do not get inherited or participate in polymorphism.
The Parent and Child classes each have their own distinct variable x. One doesn't override the other. You can use the cast to specify that you want the Parent's x, not the Child's.
With the method, it doesn't matter what cast you stick on it, when calling the Child you get the overridden version of getX. (Within a method of the Child you can call super.getX to get the parent's version of the method.)
TLDR: variable resolution rules don't apply to methods. Polmorphism doesn't apply to variables.
System.out.println(((Parent) c).getX()); //2
This dispatches to Child.getX() because of polymorphism. Then the variable resolution rules apply in the context of this method. They aren't overridden. So yes, you are essentially correct.
Polymorphism is a mechanism applied before calling a method, which always looks for the most specific override in the whole chain of subclasses, regardless of the instance's declared type.
There is no such mechanism for fields. Giving the two variables the same name "x" does not connect them in any way, so giving those two fields the same name will likely only serve to confuse future readers of your code.

Accessing parent class field "this.field" VS "super.field"

I want to know the difference between accessing parent class fields using this and super.
We have the following abstract class named ListItem which extends Node class.
public abstract class ListItem {
protected ListItem rightLink=null;
abstract ListItem next();
}
And the following code inside the Node class:
public class Node extends ListItem {
#Override
ListItem next() {
return this.rightLink;
}
But if we use the code super.rightLink, I do not get any error at compile time or runtime. I just want to know what is the difference between the both and is there a best practice to accomplish the task?
Explanation
It does not matter in this case, there is no difference.
The field is declared in the parent class. So technically super.rightLink would makes the most sense. However, super and this are only relevant for resolving ambiguous situations with variable shadowing.
The best in this case would be to leave out any prefix and just type rightLink. But this is a bit opinion-based.
Example
Suppose we have the following
public class Parent {
int variable = 1; // Field
}
public class Child extends Parent {
int variable = 2; // Field
public void foo() {
int variable = 3; // Local variable
System.out.println(variable); // 3
System.out.println(this.variable); // 2
System.out.println(super.variable); // 1
}
}
In-depth
So we have a situation with 3 different variables which all live in a different scope, but they have the same name. When you just type variable, Java will refer to the variable with the lowest scope. Which would be the local variable in the method.
If you want to access your field, you need to do this.variable. If you want to access the field of your parent, you need to do super.variable.
So again, we have three different variables here.
no prefix: lowest scope
this: field with lowest scope
super: field with lowest scope, starting from the direct parent
In your specific example, however, we have no name shadowing at all. There is only one variable with the name rightLink. So all three variants refer to the exact same variable.
The best in this case would be to use no prefix at all, just rightLink.
JLS
Let us see how the Java Language Specification defines this. and super..
For this., refer to JLS§15.8.3:
When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method or default method was invoked (§15.12), or to the object being constructed. The value denoted by this in a lambda body is the same as the value denoted by this in the surrounding context.
For super., refer to JLS§15.11.2:
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.
Unless rightLink is marked as private, it will be accessible in all classes deriving from ListItem. Thus, call super.rightLing and this.rightLink will be equivalent.
Generally, super refers to base class and this refers to class you are in. Use them appropraitely.
It's commonly used when overriding methods, i.e.
#Override
public void DoSomething(){
// Execute base imlpementation of a method
super.DoSomething();
// some additional code to add extra functionality to base class
}

Inheritance assistance for method hiding and field hiding

public class Test
{
static int i = 1;
static void m1()
{
}
}
class Test1 extends Test
{
int i = 1; //allowed
void m1() // not allowed; Both are instance level, so why this difference? Both can be accessed with super keyword
{
}
}
Why can't the static method be hidden with the same signature, but the static field is allowed to do this? Both are instance level, so why is only the static field allowed?
m1() in class Test is a static method, while m1() in Test1 is non static. Now imagine if this would have been allowed then which implementation would be picked by runtime when you execute below statement:
new Test1().m1();
Since instance of child class (Test1 in your case) can access also access static method from parent class (from Test). That is why it is not allowed.
For you next question why variable with same name is allowed in Test1: parent class' static variable can not be accessed from child class instance. In other words parent class' static state is hidden from child. That is
Test1.i; // compilation error, can't access parent's static variable
will result in compilation error. And if you try
new Test1().i; // will access Test1's i variable
it will point to the child class' state not parent's. That is why child class can have variable with the same name.
Note: If i in Test was non-static, even in that case Test1 can have variable with name i. In this case i in Test1 will shadow i in Test.
EDIT
From Shahaan Syed's comment:
new Test1().i; why is this allowed is my concerned
To put Shahaan Syed's confusion in another words: Why
in case of variable, child class can have a non-static variable while
parent class has a static variable with the same name,
on the other hand, child class can not have a non-static method when
parent class has a static method with the same name?
As Kevin Esche commented, I also think that Java messed up somewhere by allowing access to static methods of parent class from instance of child class. Though it is not a good practice and compiler generates warning as well.
Here's a quote from (JLS §8.3):
In this respect, hiding of fields differs from hiding of methods
(§8.4.8.3), for there is no distinction drawn between static and
non-static fields in field hiding whereas a distinction is drawn
between static and non-static methods in method hiding.
But I could not find any reasoning behind this in JLS.
I think instead of generating warning there should have been compile time error. That is accessing both static field and static method of parent class from child class instance, should have been compiler error. In this respect things would have been consistent and easy to understand. But again it's just my thought.
Another interesting question on the same line: Why isn't calling a static method by way of an instance an error for the Java compiler?

Java variable look up based on type not object [duplicate]

I'm wondering why Java has this strange behavior regarding a superclass and a subclass having instance variables with the same name.
Let's say we have the following class definitions:
class Parent {
int var = 1;
}
class Child extends Parent {
int var = 2;
}
By doing this, we are supposed to have hidden the superclass's variable var. And if we do not explicitly specify a way to access Parent's var via a super call, then we should never be able to access var from an instance of a child.
But when we have a cast, this hiding mechanism breaks:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.var); // prints out 1, instead of 2
Doesn't this completely circumvent the whole point of field hiding? If this is the case, then doesn't that render the the idea completely useless?
EDIT: I am referring specifically to this article in the Java Tutorials. It mentions
Within the subclass, the field in the superclass cannot be referenced
by its simple name. Instead, the field must be accessed through super...
From what I read there, it seems to imply that the developers of Java had some kind of technique in mind in doing this. Though I agree that it is a rather obscure concept and would probably bad practice in general.
In Java, data members are not polymorphic. This means that Parent.var and Child.var are two distinct variables that happen to have the same name. You're not in any sense "overriding" var in the derived class; as you have discovered yourself, both variables can be accessed independently of one another.
The best way forward really depends on what you're trying to achieve:
If Parent.var should not be visible to Child, make it private.
If Parent.var and Child.var are two logically distinct variables, give them different names to avoid confusion.
If Parent.var and Child.var are logically the same variable, then use one data member for them.
The "point" of field hiding is merely to specify the behaviour of code which does give a variable the same name as one in its superclass.
It's not meant to be used as a technique to genuinely hide information. That's done by making the variables private to start with... I would strongly recommend using private variables in virtually all cases. Fields are an implementation detail which should be hidden from all other code.
Attributes are not polymorphic in Java, and anyway declaring a public attribute is not always a good idea. For the behavior you're looking for, it's better to use private attributes and accessor methods, like this:
class Parent {
private int var = 1;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
class Child extends Parent {
private int var = 2;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
And now, when testing it, we get the desired result, 2:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.getVar());
This scenario is known as variable hiding, When the child and parent class both have a variable with the same name, child class's variable hides parent class's variable and this process is called variable hiding.
In Java variables are not polymorphic and Variable Hiding is not same as Method Overriding
While variable hiding looks like overriding a variable similar to method overriding but it is not, Overriding is applicable only to methods while hiding is applicable variables.
In the case of method overriding, overridden methods completely replaces the inherited methods so when we try to access the method from parent's reference by holding child's object, the method from child class gets called.
But in variable hiding child class hides the inherited variables instead of replacing, so when we try to access the variable from parent's reference by holding child's object, it will be accessed from the parent class.
public static void main(String[] args) throws Exception {
Parent parent = new Parent();
parent.printInstanceVariable(); // Output - "Parent`s Instance Variable"
System.out.println(parent.x); // Output - "Parent`s Instance Variable"
Child child = new Child();
child.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(child.x);// Output - "Child`s Instance Variable"
parent = child; // Or parent = new Child();
parent.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(parent.x);// Output - Parent`s Instance Variable
// Accessing child's variable from parent's reference by type casting
System.out.println(((Child) parent).x);// Output - "Child`s Instance Variable"
}
As we can see in above when an instance variable in a subclass has the same name as an instance variable in a superclass, then the instance variable is chosen from the reference type.
Declaring variables with the same name in both child and parent create confusion we should always avoid it so there will be no confusion. And this is why we should also always stick to General Guidelines to create POJOs and declare our variables with private access and also provide proper get/set methods to access them.
You can read more on my article What is Variable Shadowing and Hiding in Java.
When you are casting, you effectively tell the compiler "I know better" - it suspends the normal strong-typing inference rules and gives you the benefit of a doubt.
By saying Parent parent = (Parent)child; you are telling the compiler "treat this object as if it were an instance of Parent".
On another note, you are confusing "information hiding" principle of OO (good!) with a field-hiding side-effect (usually bad).
As you pointed out:
we are supposed to have hidden the superclass's variable var
The main point here is Variables do not override as methods do, so when you call directly Child.var you are calling a variable directly from the Child class and when you call Parent.var you're calling a variable from the Parent class, no matter if they do have the same name.
As a side note I would say this is really confusing and shouldn't be allowed as valid syntax.

Why parent class type reference variable having reference to child class object can't access child class's Methods

Since this object(stated in title) can invoke overridden methods in child class, why it can't invoke other methods of child class?
I need answer as detailed as possible like memory organization, internal logic in JVM etc.
below code will give you clear understanding of my question.
class A
{
int x=10;
public A()
{
System.out.println("Constructor of class A called!!!");
}
public void sayGreetings()
{
System.out.println("accept hye from class A");
}
}
class C extends A
{
int x=30;//why this is not accessed by stated object.
public C()
{
System.out.println("Constructor of Class C caled!!!");
}
public void sayGreetings()
{
System.out.println("accept hye from class C");
}
public void ssa()
{
System.out.println("Sat Sri Akal ji from class C");
}
}
public class ParentClassTypeObject
{
public static void main(String[] args)
{
C cObj=new C();
cObj.sayGreetings();
cObj.ssa();
A aCObj=new C();//this is let say stated object,main object
aCObj.sayGreetings();/*here we invoked method will be child class's
overriden method.*/
//aCObj.ssa(); //why this line gives error
System.out.println("x="+aCObj.x);
}
}
Because the interface you have to the object is the one you chose when you wrote:
A aCObj = new C();
If you want access to the C properties via the aCObj variable, declare it as a C.
By making it an A, you make it possible to write this later:
aCObj = new A();
So since the variable can point to an A, or a C, the compiler restricts you to accessing the methods defined by the interface exposed by the A type.
You still access C's definition of those methods, because that's one of the main points of OOP (polymorphism).
Reference Variable points to the object which is of same type or the Sub set of same type.
Please consider Parent and Child are two classes Where Parent is Super Class and Child inherits the Parent Class. The below image will give you a detailed explanation.
In the above picture, The Parent class Reference variable will search for the Parent Class Object in Child Object.It will find it , as it is there.So will give the output.And if you have the Same method in Child Class(Method Overriding) It will execute the child class overrided method.
But for the Child Class reference Variable ,It can not find out the child class object in Parent Class Object.So here,It's Not possible.
Hope This clear your Confusion.
If you compile the code you will get compile time error(not runtime error). The reason behind this is that
A aCObj=new C();
aCObj.sayGreetings();/* The compiler knows that aCobj is a reference of type A while compiling. Since compiler thinks aCobj is of type A and sayGreetings() method is present in class A so no error while calling this method */
aCObj.ssa(); /* As I mentioned above that compiler have no knowledge about run time. At run time aCobj will point to the object of type class C, but while compiling the compiler only knows that aCobj is of class A type and since class A have no such method called ssa(), you will get compile time error. */
One simple rule for object : Left side of assignment operator checking at compile time. Right side of assignment operator at run time.
Consider this statement:
Parent obj =new Child();
obj.method1();
obj.method2();
Whatever method u want to call using obj reference of Parent type, those method should present in Parent class because during compile time the compiler will strictly check for those methods presence in Parent class even though it may be present in Child class.
The compiler decides IF you can call a method based on the type of the reference variable.So if the reference variable is of class A you can only call methods of class A.
But also
the compiler decides WHICH method to call based on the actual type of the object and not the type of the reference variable starting a bottom up check on the inheritance tree.(it starts from the subclasses all the way up)
So in this case when you say aCObj.sayGreetings(); the compiler firstly checks the reference type of aCObj which is A.Class A has the sayGreetings() method so its ok.But the actual object is a C.So the compiler starts from subclass (C) to find whether this method is implemented all the way to the superclass (A).The method `sayGreetings() is overriden at C class. So it calls the C class sayGreetings() method(of the subclass).
On the other hand the ssa() method is of class C and since the reference variable is of class A the compiler gives an error when you try aCObj.ssa();
It's just polymorphism.Since an A class reference variable can be either A or C object the compiler restricts the access only to the methods that are common which are the methods of the superclass A.Next it checks whether this method is implemented at the class of the actual object (C).if it is not it moves up to the superclass (A) and calls the method of the superclass.But if it is implemented it calls the method of the subclass (C)
The Object is of type A not C so you cannot access the instance variable i think if you make it public then you can.
Because aCObj is declared as type A so only methods declared in type A are accessible. The compiler cannot guarantee it is also of type C.
E.g.
You may also have
public class B extends A {
public void sayGreetings() {
...
}
}
This does not have the ssa method, but could still be assigned to an object declared as type A
Case 1. The reference variable of a parent class can point to an object of its child class..
Case 2. The reference variable of a parent class that is pointing to an object of its child class can be typecasted to an object of its child class.
In case 1: reference variable of a parent class can only call the methods that are defined within the parent class and also it can call the methods of child class that are overriding the methods of parent class.But cannot call the methods that are exclusively only in child class.
In case 2: reference variable of a parent class can call the methods of its child class also.
This is due to the principle of Polymorphism.
here is the detailed explanation of your stated query:
The answer is the intersection of "polymorphism" and "static typing". Because Java is statically typed at compile time you get certain guarantees from the compiler but you are forced to follow rules in exchange or the code won't compile. Here, the relevant guarantee is that every instance of a subtype (e.g. Child) can be used as an instance of its supertype (e.g. Parent). For instance, you are guaranteed that when you access employee.getEmployeeDetails or employee.name the method or field is defined on any non-null object that could be assigned to a variable employee of type Parent. To make this guarantee, the compiler considers only that static type (basically, the type of the variable reference, Parent) when deciding what you can access. So you cannot access any members that are defined on the runtime type of the object, Child.
The answer has been taken from the following link:
Why do we assign a parent reference to the child object in Java?

Categories