How many objects are created in inheritance? [duplicate] - java

I have a question about inheritance in Java.
I have two classes A and B , and class B, inherits from A:
public class A {
public A() {
System.out.println("Hi!");
}
}
public class B extends A {
public B() {
System.out.println("Bye!");
}
public static void main(String[] args) {
B b = new B();
}
}
When I run program B, the output is:
Hi!
Bye!
Question : why the constructor of class A is invoked, when I create and object of class B ?
I know that B inherits everything from A - all instance or class variables, and all methods, and in this sense an object of B has all characteristics of A plus some other characteristics defined in B. However, I didn't know and didn't imagine that when I create an object of type B, the constructor of A is also invoked.
So, writing this:
B b = new B();
creates Two objects - one of type B, and one of type A.
This is getting interesting,
can somebody explain why exactly this happens?

It doesn't create two objects, only one: B.
When inheriting from another class, you must call super() in your constructor. If you don't, the compiler will insert that call for you as you can plainly see.
The superclass constructors are called because otherwise the object would be left in an uninitialized state, possibly unbeknownst to the developer of the subclass.
Your subclass actually looks like this after the compiler inserts the super call:
public class B extends A {
public B() {
super();
System.out.println("Bye!");
}
}

It doesn't create 2 objects, it only creates one instance of B. The reason the super class constructor is invoked is because, like you said, B has all of the fields of A, and these fields need to be initialized.

Remember inheritance is an "is a" relationship between the base class and the subclass, thus every time you have an instance of a subclass, by definition you will also have an instance of the base class (as part of the instance, not as two separate instances). To initialize the base class properly the constructor is called.
Additionally, think about what would happen if you subclass depended on some internal state of the base class. Wouldn't you want the instance of the base class to be initialized then?

This is done because the constructor is used to initialize the object. Since B is also an A, it calls the constructor for A first, then the constructor for B.
As a side note, you can use super(arg1, etc) to choose which constructor of A is called based on the parameter types you pass... but it must be the first line in the constructor.

The constructor contains all of the initialization for A. You are not creating two objects. You are creating one object, then running the initializer for the superclass to initialize its members, and then running the initializer for the deriving class to initialize its members.

It does not create two objects, it just creates one object b. b is of type B and of type A. A constructor is basically saying here is what you need to do to construct me. So when you are creating a new "B" instance, you are building an object that is both a B() and an A(). Imagine the following scenario:
class Q {
int i;
public Q() {
// set default value
i= 99;
}
}
class Z extends Q {
public Z() {
}
}
If the constructor for Q WAS NOT called, how would i get its default value?

The creation of B does not create an extra A.
But by creating B, you create a kind of A, because B is a A.
Java/C++ call the constructor of A for your implicitly. Why? Language design. But doing so is fine, because the constructor of A might contain some initializations. And as B uses all the features and bugs of A, these features better be initialized properly.

The constructor of a class is very important concept in most OOP
Classes, by providing state and the means to manipulate that state, allow the easier maintenance of invariants. The constructors role is to get the class into a state that conforms to those invariants (or throws thus forbidding usage of an invliad object).
this is somewhat looser than intended in many languages since the constructor is allowed to pass its own 'this' reference elsewhere but this is at least under the control of the class (as such it can know that it is in a sufficiently stable and valid state for it to be accessible to the rest of the world)
Inheritance makes this complex since B is-a A in a very real sense and thus can invoke any of the methods provided by A. The parts of B that are A should therefore get their chance to initialize themselves before B gets a look in, thus the constructor for A is called before the real work of the B constructor begins.

If A intializes members in it's constructor and you forget to call super in your derived class then the members of A could be in a bad state. Java is trying to stop you from shooting yourself in the foot.

Only one object is created, both contractors are running on the same object.
The reason is simple, as you know B has all the variables and methods of A, so if some variable of A needs initializing so methods of A can work someone has to initialize it - and that someone is A's constructor.
for example:
public class A {
public A() {
x = 1;
}
private int x;
public int getX() {
return x;
}
}
public class B extends A {
public B() {
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.getX()); // should print 1
}
}

When new object is create(B), inside B A object is created(because of extends keywords) . In B class JVM search B class constructor, but due to extends keywords it goes to super class constructor. inside A class x value is initialized. But x is private so that we can access outside class throw getXxx() method and get the result.

When sub class object is created then internally it was not created for super class object.But the memory should be allocated for super class members.

In java when you create an object of child class the constructor of parent class is always called because Object class is the parent of every super class and when you call the constructor of Object class then only your object is created and java does not support multiple inheritance in case of class so if you extends any other class then the relationship between you child class and the Object class is through the Parent class so to call the constructor of the Object class the constructor of Parent class must be called.

Every superclass has a constructor and each constructor up the hierarchy runs at the time an object of a subclass is created.

if super class object is not created then how sub class is accessing super class non static methods and variables.
I studied that non-static methods and variables can be accessed only through objects..

Related

How many objects were created where B is inherited from A?

Here are two classes,
class A
{
}
class B extends A
{
}
and A is inherited from B.What confuses me is that How many objects were created when I use the following code
A a = new B();
I know when I create an instance of B ,it will first call A's constructor and then call the constructor of B's.
Was there an instance of A been created when call A's constructor?
How many objects were created in
A a = new B();
It creates a single object, which is an instance of B. It's already a B when the A constructor executes, as you'll see if you change your code to:
class A {
public A() {
System.out.println(getClass());
}
}
class B extends A {
}
...
A a = new B(); // Prints B in the A constructor
Basically, the constructor isn't what creates an object - it's what initializes an object in the context of that class.
So you can think of the steps as:
Create object of type B
Initialize the object in the context of A (field initializers, constructor body)
Initialize the object in the context of B (field initializers, constructor body)
(with constructor chaining up the inheritance tree evaluating constructor arguments, of course... while the constructors are sort-of called going up the chain too, as the first part of any constructor has to chain to the same class or a superclass, the main part of the constructor body happens top-down).
For rather more detail about exactly what happens, see JLS 15.9.4 and JLS 12.5.
One object is created, which is a B object, which has both the aspects defined by A and the aspects defined by B. Since it incorporates all of the aspects defined by both of them, it's instanceof both A and B.
...and A is inherited from B
A is inherited by B, not from it. (The little words are the hardest in a non-native language.) B inherits from A. Some usual terms around this: "B derives from A", "B is derived from A", "A is a superclass of B", "B is a subclass of A".
Was there an instance of A been created when call A's constructor?
Despite their name, constructors don't create objects; they initialize them; and this question is why: Sometimes to correctly initialize the object, you have to call multiple constructors (one for each level in the object's inheritance hierarchy). In new B(), the JVM creates the object, then calls B with this set to that new, blank object so B can initialize it. The first thing B does is call A to let it initialize the A aspects of the object, then B initializes the B aspects of the object. E.g.:
JVM creates object.
JVM calls B
B calls A
A initializes the aspects of the object it's responsible for and returns
B initializes the aspects of the object it's responsible for and returns
Only one instance of B is created.
Constructors can be called up the chain, but each call only acts on the single instance that you're creating.
As those above me already said: Only one object is created. To clarify this you might think of the three parts of the statement you just wrote down:
A a = new B(). These are the part of declaration A a, the part of instantiation new and the part of initialization B().
If you want to read up on this topic (because perhaps not everything got clear to you), consider visiting https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html

Java Inheritance: Difference while inheriting super class members and variables

I was going through Java inheritance and I tried the following code
class A {
public int x = 1;
public void print1() {
System.out.println("Print from A");
}
}
class B extends A {
public int x = 2;
public void print1() {
System.out.println("Print from B");
}
}
class C extends B {
public int x = 3;
public void print1() {
System.out.println("Print from C");
}
public static void main(String aa[]) {
C c = new C();
((A) c).print1();
System.out.println(c.x);
System.out.println(((A) c).x);
}
}
The output was
Print from C
3
1
Now, my question is that I am able to access class A member x from class C instance c but why am I not able to access the class A method print1(). I know, if I want I can call new A().print1();. But, I want to access it from an instance of class C directly. So by overriding methods, are the top parent class methods lost in the bottom child class? However, the parent class members are retained (although hidden). Why so? And is there a way to call a method from class A in class C without creating an instance of A?
EDIT
What's happening here?
When you say ((A)c).print1();, JVM knows that actual the instance, on which it needs to call is print1() is of type C hence class C's print1() version is executed.
But when you type ((A)c).x, you are referring to state, not behavior and that too using reference of type A. Which version of x will be picked up, is decided at compile time as compiler knows what is the type reference (In this case A). That is why you see A's state.
This statement from Java doc might also be interesting for you:
Within a class, a field that has the same name as a field in the
superclass hides the superclass's field, even if their types are
different. Within the subclass, the field in the superclass cannot be
referenced by its simple name. Instead, the field must be accessed
through super, which is covered in the next section. Generally
speaking, we don't recommend hiding fields as it makes code difficult
to read.
Why is it this way?
Answer to your questions:
Question 1:
my question is that I am able to access class A member x from class C
instance c
About variable x, since it is declared as public, no business validation can be applied on that. Moreover, the developer who's declaring it as public, is aware that concept of encapsulation can't be applied now (which is obviously not recommended). So there is no harm in allowing access to parent's state using child instance. Therefore, by using ((A)c).x, you can access x from class A.
Question 2:
However, the parent class members are retained (although hidden). Why
so?
It's because Java does not allow you to use super.super.super.. arbitrarily to access any parent's behavior in the inheritance hierarchy. And the reasoning behind it is to preserve encapsulation. You can only access behavior of the immediate parent class using super keyword but not beyond that.
To explain it more, let's say you have implementation of class B like:
class B extends A {
public int x = 2;
public void print1() {
if(x >= 2) {
System.out.println("Print from B");
}
}
}
Now if super.super was allowed, you can easily bypass validation in print1() method of class B and can invoke A's print1() method from the instance of class C.
Question 3:
However, the parent class members are retained (although hidden). Why
so?
As, mentioned earlier, to retain encapsulation.
Question 4:
And is there a way to call a method from class A in class C without
creating an instance of A?
So there is no way to access print1() from A using C's instance.
When you override a function which already implemented in base(parent) class, when you call that function within the child class, automatically the class in the child will call so in your case when you call print1() of a C object:
C c = new C();
c.print1();
you will call the override function. However if in any part of your program you feel that you need to call the top parent class for any case (which cannot be fulfilled by super) then you should reconsider your design strategy; maybe you shouldn't override the print1() or even you shouldn't put print1() in the base class in the first place
In object oriented programming, only methods have the ability to be overriden. You cannot override a data member. This explains why you get the outputs.
print1() method of A is overriden in C, and c is an object of C. So, it will call the print1() method of C. On the other hand, the variable x is not overriden.
To call the superclass method, you can do:
super.print1();
Here , Same named Instance Variable is used in all the Classes to confuse the compiler, but you should know that Only Member functions can be overridden not member variables.
So, All the three x will be stored separately in memory. but public void print1() will be overridden by its child class. So,
((A)c).print1(); this piece of Code will Call the overridden method defined in class C. doesn't matter in which class you cast the Object of Class C.
But in Second Case ((A)c).x will print the value from Class A.
((A)c).x :- this will reference to the variable x belongs to Class A not to Class C. because variables never overridden in Inheritence.
((A)c).print1(); Actually it is similar to the c.print1(); .
It doesn't matter that you typecast it with Class A, it will still call print1() function of the Class C.

Why can't outer classes extend inner classes?

Why can't I do this/is there a workaround to accomplish this:
package myPackage;
public class A {
public class B {
}
}
package myPackage;
import myPackage.A.B;
public class C extends B {
}
package myPackage;
public class Main {
public static void main(String[] args) {
A myA = new A();
C myC = myA.new C();
}
}
The two compilation errors are
On public class C extends B, No enclosing instance of type A is available due to some intermediate constructor invocation
On C myC = myA.new C();, A.C cannot be resolved to a type
Frankly, I think the conceptual idea is sound: I want to make a subclass of B so that when I make a B for A, I have the option of making it have the functionality in B or the functionality in C.
Four workarounds/solutions that I don't want, and why I don't want them:
"Solution: Put C inside of A." I don't want this because what if I can't modify the code for A.java (there are applications that have this restriction)? What if A is part of another API? Then I have to create a new file for C, as I've done here.
"Solution: Put C inside of a class D that extends A." I don't want this because then C is restricted to only being instantiated on instances of type D. I want to make a class that extends B that can be instantiated on all instances of type A (there are applications that need this). Therefore, I need C to not be enclosed by another class, as I've done here.
(Added as a question edit - see JoshuaTaylor's answer for a code sample) "Solution: Make B static." I don't want this because what if functionality in B needs to access its enclosing instance of A (there are applications that need this)? Therefore, I need B to not be static, as I've done here. (2nd question edit: You could make B static and have its constructor take in its enclosing instance, saving it in a protected variable for access in its children, but this is less elegant than the accepted answer by RealSkeptic)
Removed. See edit at bottom.
So, if your answer suggests that I do one of the above, it is not an answer to this question, even though it might be useful for other people.
If your answer is "This is just a flaw of the Java language, you simply can't accomplish that conceptual idea", that is an okay answer, and you should post it. Just a warning though: I will hold off on marking your answer as accepted in case you are wrong. If this is your answer, I would highly appreciate if you have an explanation for why this restriction on the language is in place (as that's the title of this question).
Thank you for any and all help.
EDIT: JoshuaTaylor's answer brings up a valid option: you can extend B anonymously and avoid having to write a constructor as in RealSkeptic's accepted answer. I originally discarded this idea because it does not allow you to access C's enclosing instance of A via "A.this". However, I have since learned that C does not have an enclosing instance of A unless it is specifically defined within the definition of A as a nested class. So please note: none of the solutions below allow you to access the enclosing instance of A that encloses C's ancestor of B via writing "A.this" in a method of C. Classes can only use ".this" to access types which they are specifically nested in. However, if B has functionality that accesses the enclosing instance of A, either an anonymous class via JoshuaTaylor's method or any other class via RealSkeptic's method is required.
Well, it can be done, but you have to remember that each constructor needs to call its super constructor, explicitly or implicitly. That's why you get the "No enclosing instance of type A is available due to some intermediate constructor invocation" error. C's no-args constructor is trying to implicitly call B's no-args constructor, and it can't do that without an A.
So you fix your C to be:
public class C extends B {
public C(A enclosing) {
enclosing.super();
}
}
And then you can create a new C by using:
A myA = new A();
C myC = new C(myA);
Answers to the questions in the comments
#Andi Turner asked:
If you are explicitly passing in an A to the constructor of C, can't C now be static, and have A as a "plain old" member variable in C on which you invoke the required methods?
It should be noted that C is neither static nor an inner class. It is an individual public class which is extending an inner class B. The implementation of the class B may not be known to the author of C, so it cannot know what methods would be using A, nor does it have access to any private members of A, as C is not a member of A. But B does, and B requires the A instance. An alternative approach would be composition rather than inheritance (where C holds a B instance and delegates operations to it), but if it wants to create that B instance rather than have it passed inside, it will still need an A instance, although it will use enclosing.new B rather than enclosing.super.
#rajuGT asked:
Is C is an individual entity? if so, why does it need A object? and what is the association between myA and myC in this case?
Yes, C is an individual entity. It wouldn't need A for any of its own methods. But if it tries to call (or inherits and doesn't override) methods from B that involve access to A - then that A is required by the implementation of B. Formally, of course, any instance of B requires a reference to A even if it doesn't actually make use of it. The association between myA and myC are is that myA is the immediate enclosing instance of myC with respect to B. This term is taken from section 8.1.3 of the JLS:
For every superclass S of C which is itself a direct inner class of a class or interface SO, there is an instance of SO associated with i, known as the immediately enclosing instance of i with respect to S. The immediately enclosing instance of an object with respect to its class' direct superclass, if any, is determined when the superclass constructor is invoked via an explicit constructor invocation statement (§8.8.7.1)
Official reference for this usage
This usage is known as a qualified superclass constructor invocation statement, and is mentioned in the JLS, section 8.8.7.1 - Explicit Constructor Invocations.
Superclass constructor invocations begin with either the keyword super
(possibly prefaced with explicit type arguments) or a Primary
expression or an ExpressionName. They are used to invoke a constructor
of the direct superclass. They are further divided:
Unqualified superclass constructor invocations begin with the
keyword super (possibly prefaced with explicit type arguments).
Qualified superclass constructor invocations begin with a Primary
expression or an ExpressionName. They allow a subclass constructor to
explicitly specify the newly created object's immediately enclosing
instance with respect to the direct superclass
(§8.1.3).
This may be necessary when the superclass is an inner class.
At the end of that section, you can find examples for explicit constructor invocation statements, including this usage.
You can easily extend nested static classes
Update: You've mentioned that you don't want this first solution, but the phrasing of the question may lead people to it who are willing to have the inner class be static, so I'll leave this in the hopes that it's useful to them. A more proper answer to your exact question is in the second section of this answer.
You can, but the inner class has to be static, because if it's not, then every instance of the inner class has a reference to the enclosing instance of the outer class. A static nested class doesn't have that reference, and you can extend it freely.
public class Outer {
public static class Inner {
}
}
public class InnerExtension extends Outer.Inner {
}
But you can also extend nested non-static classes
package test;
public class Outer {
public class Inner {
public String getFoo() {
return "original foo";
}
}
}
package test;
public class Extender {
public static void main(String[] args) {
// An instance of outer to work with
Outer outer = new Outer();
// An instance of Outer.Inner
Outer.Inner inner = outer.new Inner();
// An instance of an anonymous *subclass* of Outer.Inner
Outer.Inner innerExt = outer.new Inner() {
#Override
public String getFoo() {
return "subclass foo";
}
};
System.out.println("inner's class: "+inner.getClass());
System.out.println("inner's foo: "+inner.getFoo());
System.out.println();
System.out.println("innerExt's class: "+innerExt.getClass());
System.out.println("innerExt's foo: "+innerExt.getFoo());
}
}
inner's class: class test.Outer$Inner
inner's foo: original foo
innerExt's class: class test.Extender$1
innerExt's foo: subclass foo

Why can a super class be initialized as a child class in Java?

In a nutshell, how and why is this possible:
Object obj=new MyClass();
Object is the superclass of all objects, therefore MyClass is a child class of Object. In general, in Java, Why is it possible to use the constructor of a child class in the parent class?
I understand how it could go the other way around, since the child has all the variables/methods of the parent class, so when you initialize them you are just initializing the variables specified in the parent constructor, that exist by definition in the child. The problem is, when you go the other way around, it is not necessarily true. A child can have variables the parent doesn't, so how is it possible to use the child constructor with the parent, when the parent does not even have the variables in the first place?
What uses does this feature have in development? I would think that if you want an instance of class B, you would declare it as B thing=new B(), and not A thing=new B(). This is probably my inexperience talking, so I would appreciate enlightenment on why and how a parent class can be initialized as one of its children.
Why is it possible to use the constructor of a child class in the
parent class?
This is not correct. When you do
Object obj = new MyClass();
Object obj; declares a reference of the type Object
and new MyClass(); returns a reference to the object it created.
So, you are instantiating a MyClass and assigning the reference to the object created to a reference of the type Object, and this is possible because MyClass is an Object.
As you say,
A child can have variables the parent doesn't
That's called extending the parent functionality (inheritance).
For your second question think about the classic Animal example: Suppose you create a Animal class and you create a method makeSound() on it.
Now you create two subclasses of Animal, Dog and Cat, that overrides the makeSound()method of Animal (a Dog barks and a Cat meows).
Imagine that you represent a room full of Animals (Dogs and Cats) using a List, and you want to make all of them makeSound(). Your list will be declared as List<Animal> because you don't know the kind of Animals that you will store.
And then you iterate over the List to call makeSound() for each Animal. It doesn't matter if the Animal is a Dogor a Cat, it will make it's sound.
And then imagine you want to add Birds to the List. Easy, isn't it?
You are thinking in terms of C++ semantics, but this is Java. In Java, all non-primitive type variables are references, not instances.
In C++, when you say
Object obj;
you allocate a new Object instance on stack or in static memory.
When you say
Object obj = new MyObject;
you invoke a constructor of Object class that takes MyObject pointer (or may be something else that MyObject can be converted to).
In Java,
Object obj;
does not create any instances of Object. It simply creates a variable that can have a reference to an Object instance, but at the moment does not refer to any. It is initialized to null.
Object obj = new MyObject();
allocates an instance of MyObject. It does not allocate a new instance of Object. It simply sets the variable to refer to the new instance. In C++ terms this is much more similar to
Object *obj = new MyObject();
So we're not constructing a parent instance from child instance. We're changing a value the variable is set to, from null to a new child instance.
First, you must get a clear understanding of things. Your example expression:
Object obj = new MyClass(); is actually a compound of two elementary operations.
The first one is creating an instance of MyClass: new MyClass(). The new keyword is basically the only way of actually obtaining an instance of a class (lets ignore runtime reflection to keep this simple), and you are literally naming what you want to create (MyClass) here by its constructor. There is no way to create anything other than what you literally named with the new keyword. The result of new is (implicitly) an instance of MyClass, but the explicit result of a new X is a reference of type X (the reference referring to the newly created instance).
Now the second operation is assigning the reference to your (new) MyObject to another reference of type Object. And this is valid because MyObject is an Object (due to inheritance).
Why would you need this?
This is an essential feature to actually make use of polymorphism. The ability to refer to any child class as its superclass is what makes polymorphism so powerful. You basically will use it everywhere where there is an aspect common to two classes, but there are also differences.
A real world example would be graphical user interfaces. There are buttons, lists, tables and panels in a window, which are all user interface elements, but each does a different thing. To present them neatly organized in a window, these elements are often nested into panels, more abstractly said into containers. Now a container doesn't care what kind of elements go into it, as long as they are components. But to handle them properly a container does need some basic information about these components, mostly how much space they occupy and how to actually draw them. So this is modelled as something like:
public abstract class Component {
public int getWidth() { ... }
public int getHeight() { ... }
public void paint(Graphics g) { ... }
}
public class Container extends Component {
public void add(Component child) { ... }
public void paint(Graphics g) {
for (Component child : children) {
child.paint(g);
}
}
}
Thats almost straight lifted out of the JDK, the point is, if you needed to refer to each Component as its concrete type, it would be impractical to build a Container, it would need extra code for each Component you decide to make (e.g. there would be an addButton, addTable and so on). So instead, Container just works with reference to Component. No matter what Component is created (e.g. Button, CheckBox, RadioButton etc.), since Container just relies on them to all be Component's, it can handle them.
Every class in Java is descended from Object. So MyClass is an Object, by definition, but a more specialized version of it. Think of it like this: every living creature is an Animal. A Cat is a special kind of animal; a specific type. Since the Cat is an Animal, you can still just call it an Animal:
Animal a = new Cat();
But doing so, with a, you can't do anything specific to a Cat, like meow() or purr(), but you can call methods which are valid for all Animals, such as breathe().
HTH
class myMobile{
public void call{
System.out.println("Mobile");
}
}
public class mainClass{
public static void main(){
Object o=new myMobile();
//here we can call methods which are common to all
// objects not specific to
// myMobile object
}
}
Because a MyClass is a Object. Note that java is special because Object is the superclass of every other class type (there is no equivalent in C++).
A more interesting example would be if you had a class or interface and one or more subclasses. This comes up all the time in OOD. Consider for example java's jdbc API: a common set of interfaces to connect and query a database that can be implemented by different concrete classes. You only need to code to the API and then at runtime use the implementation for your DB of choice.
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.
i.e. every Java class is an Object. This is why.
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
The Object class, defined in the java.lang package, defines and implements behavior common to all classes—including the ones that you write. In the Java platform, many classes derive directly from Object, other classes derive from some of those classes, and so on, forming a hierarchy of classes.
You have two separate things here:
The construction of a new instance
The assignment of that instance to
a variable
Since your instance of MyClass is also an instance of Object, this works well.
Consider the following, generic situation:
class A extends B implements C,D {
}
As your A is a B and also a C and a D and an Object, once you created an instance, you can (directly or indirectly) assign it to variables of all those types:
A a = new A();
B b = a;
C c = a;
D d = a;
Object o = a;
Your view on the fields or methods is limited by the type of the variable (i.E. as variable of type C, you only see the methods declared by C).
Nevertheless, your instance is always of the type you instanciated using the constructor, regardless of the variable type.

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