I am trying to learn about inheritance and I came across this problem.
Here is the code:
import java.util.*;
class Parent
{
void show()
{
System.out.println("show from parent");
}
}
class Child extends Parent
{
public static void main(String s[])
{
Parent p=new Child();
p.show();
p.display();
}
void show()
{
System.out.println("show from child");
}
void display()
{
System.out.println("display from child");
}
}
And the error is:
G:\javap>javac Child.java
Child.java:15: error: cannot find symbol
p.display();
^
symbol: method display()
location: variable p of type Parent
1 error
If I'm able to access show() then why am I not able to access display() knowing that display() is inherited and is also present in the class definition of Child class.
You must understand the distinction between the run time type and the compile time type.
At run time your variable p holds a reference to a Child instance. So calling the show method will run the code in Child#show because this overrides the method Parent#show.
At compile time, the compiler can only know about the declared type of the variable. And this is Parent. So the compiler can only allow access to the fields and methods of type Parent, but not of type Child.
The display method simply isn't declared in Parent, hence the error.
if u want to call the display method of client then you must need to create object of child class.
eg.
Child child=new Child();
otherwise you need to write display method in parent class.
the rules is reference of parent class cant call member of child.
Display() method not in parent class.that is the error .you are access parent class show method not child class.if you are trying to access method in parent class using object you dont need methods in child class
Related
Given the code from Parent class and Child class:
class Parent{
public static void classMethod(){
System.out.println("ClassMethod in Parent");
}
public void hello(){
System.out.println("Hello from parent, call classMethod");
classMethod();
}
}
class Child extends Parent{
public static void classMethod(){
System.out.println("ClassMethod in Child");
}
}
If I have this in main method:
public static void main(String[] arg) {
Parent D = new Child();
D.hello();
}
Why is this the result? ->
Hello from parent, call classMethod
ClassMethod in Parent
So there's a child object of parent class calling an instance method which calls a static method.
I would understand why it calls the static method from the parent class if hello() was static as well, since the object type would be defined at compile time and it would be Parent. However, since hello() here is an instance method, it has to be resolved at runtime, and at runtime, isn't the type of the object the actual type, AKA Child type? So in that case, wouldn't it call the static method from the child object since the object is of child type at run time?
Note: this answer assumes the Child class extends Parent. Otherwise, the code in the main method just throws an error.
This is an example of up-casting and polymorphism. Because it's of the type Parent, its access is limited to the Parent class. When you call the hello() method, it is being called in the Parent class. Then, this method calls classMethod() but, because hello() is a method in the parent class, it calls it in the Parent class as well, which is why you are getting that as a result. The fact that it is static makes no difference: static methods can always be called by instance methods, but not always the other way around.
One thing I should point out is that, because of the line Parent D = new Child();, the object D does not actually have access to any of the static methods in Child even though it is that type. If you wish for D to have access to methods in both Parent and Child, you can use Child D = new Child();
With Parent D = new Child();, if you are calling a method, it must be in the Parent class and will run the method in the parent class - except for if there is an overriding instance method of the same name in the Child class, in which case it will run this method instead. It should also be noted that an overridden method cannot be static
Why reference variable of child class can't point to object of parent? i.e
Child obj = new Parent();
However we can do vice versa
Kindly answer with memory view (heap)
There is no reason which has something to do with the memory. It's much more simple. A subclass can extend the behaviour of its superclass by adding new methods. While it is not given, that a superclass has all the methods of its subclasses. Take the following example:
public class Parent {
public void parentMethod() {}
}
public class Child extends Parent {
public void childMethod() {}
}
Now let's think about what would happen if you could assign an instance of Parent to a variable of type Child.
Child c = new Parent(); //compiler error
Since c is of type Child, it is allowed to invoke the method childMethod(). But since it's really a Parent instance, which does not have this method, this would cause either compiler or runtime problems (depending on when the check is done).
The other way round is no problem, since you can't remove methods by extending a class.
Parent p = new Child(); //allowed
Child is a subclass of Parent and thus inherits the parentMethod(). So you can invoke this method savely.
The answer is too late.
I believe we can explain it in terms of memory. Maybe I'm wrong but this is what I'm thinking about this scenario.
// Assume, Required 2KB for execution
public class Parent {
public void display(){
System.out.println("From Parent");
}
}
// Total memory required for execution : 4bk
public class Child extends Parent {
#Override
public void display() {
super.display(); // 2KB
}
public void sayHello() {
System.out.println("From Child - Hello"); // 2KB
}
}
//2KB expect //4KB assigned
Parent parent = new Child();
//4KB expect //Only 2KB is assigning
Child child = new Parent();
Here the 'CHILD' class variable is expecting 4KB memory, but we are trying to assign 2KB 'Parent' class objects to it. So the compiler throwing exception.
In Java, when a method is going to be executed, it's declaration is first searched for at the object's real class (that defines the real type of the object). If it's not found, then the superclass is checked. If isn't found there either, the next parent class is checked, and so on. However, look at the example below:
SuperClass s = new SubClass(list of parameter);
s.someMethodExistOnlyInSubClass();
This will give me a compile time error. I thought that, as mentioned above, it would first look for someMethodExistOnlyInSubClass() at SubClass, verify that it exists there and then execute it right away. If I use a variable of the type SuperClass to reference an instance of SubClass some parameters will go to SuperClass's constructor through a call to super() and the object will be instantiated there. In this context, to where have the remaining parameters gone?
By assigning a reference to an instance of SubClass to a variable of the type SuperClass, the variable is treated as if it were referencing an instance of SuperClass. Therefore, it will have no knowledge of any of the methods declared specifically in SubClass. Note, though, that the overrides performed in SubClass will still be effective.
In the context you described, to access someMethodExistOnlyInSubClass() you would have to cast s to the type SubClass. Look below:
((SubClass) s).someMethodExistOnlyInSubClass();
What you are trying to do will work only when the method is defined in both Parent class and subclass.
import java.util.*;
class Parent
{
public void sample()
{
System.out.println("Method of parent is getting Called");
}
}
class Subclass extends Parent
{
public void sample()
{
System.out.println("Method of Child class is getting Called");
}
}
public class Main
{
public static void main(String[] args){
Parent p = new Subclass();
p.sample();
}
}
OUTPUT : Method of Child class is getting Called
If the method exists only in Child class. You will have to create an instance of Child class itself.
Something like this :
import java.util.*;
class Parent
{
}
class Subclass extends Parent
{
public void sample()
{
System.out.println("Method of Child class is getting Called");
}
}
public class Main
{
public static void main(String[] args){
Subclass p = new Subclass();
p.sample();
}
}
Or you can type cast it as mentioned in the earlier post
Parent p = new Subclass();
((Subclass)p).sample();
An object is created based on its declaring class.
When you declare it as SuperClass s the object s wont have any method called someMethodExistOnlyInSubClass . So when you try to invoke this method, even before look at the subclass, you get a compile error.
The object s contrains only everything of the superclass, this object wont be aware of any subclass until u type cast the object to subclass.
public class Parent {
public void printParent()
{
System.out.println("I am the Parent");
System.out.println("----this is ::---" + this);
this.printChild();
}
private void printChild()
{
System.out.println("This is my child");
}
}
public class Child extends Parent {
private void printChild()
{
System.out.println("I am the child");
}
}
public class RelationshipTester {
#Test
public void testRelation()
{
Child parent = new Child();
parent.printParent();
}
}
This is the output :-
I am the Parent
----this is ::---datastructures.lists.inheritance.Child#1a692dec
This is my child
The object is of the type Child , yet it doesn't call the child method and the parent one. I have given this.printChild();
In the Parent class, you have declared printChild as private ... and called it. A private method cannot be overridden. Your printChild in the Child class is not known to the Parent class.
If you were to change the private modifier to public, then you would have an override, and your example should output what you are expecting.
Why won't Java let you override a private method? Well, basically, if you could do it then there would be no way to write a class with an abstraction boundary that a child class could not break. That would (IMO) be a major language design short-coming.
Why doesn't Java report an error or warning? Well there is no error because this is legal Java according to the JLS. As for a warning ... if you compile Parent in isolation there is no problem, because the code as written is declaring and using a private method. If you compile Child in isolation, the compiler can't see the private method in the Parent class. (Indeed, it may not even exist in the version of the .class file for Parent that you are compiling against.) Only if you compiled Parent and Child at the same time might the compiler spot something a bit odd.
The keyword 'this' point to the current class instance and here is the private void printChild(). And then you have created an object of class Child at RelationshipTester class. The scope of the two function is private which means to is bounded to that class only. Thus, it won't overwrite the subclass and would execute the Base class's method.
private methods are not inherited. When you call printParent, you're calling a method on Parent and when that method refers to this, it's referring to an instance of that class (Parent), which has its own printChild method. Making Parent#printChild a protected method should give the expected result.
public class Child extends Parent {
protected void printChild(){
System.out.println("I am the child");
}
}
use protected, not private
In this program we have to remember 2 points:
If we create an object for a subclass (here child) then memory also created for the super class. That means if the method that we are calling that is not found in the child class then Java Virtual Machine goes to parent class and checks for the method that we are calling and if the method is found it will execute. If the method is found in child class itself it will not go to the parent class.
private, static and final methods can't be overridden.
Since the scope of the method is private it is not visible to other class.
Why does is print last "I'm a Child Class." ?
public class Parent
{
String parentString;
public Parent()
{
System.out.println("Parent Constructor.");
}
public Parent(String myString)
{
parentString = myString;
System.out.println(parentString);
}
public void print()
{
System.out.println("I'm a Parent Class.");
}
}
public class Child extends Parent
{
public Child() {
super("From Derived");
System.out.println("Child Constructor.");
}
public void print()
{
super.print();
System.out.println("I'm a Child Class.");
}
public static void main(String[] args)
{
Child child = new Child();
child.print();
((Parent)child).print();
}
}
Output:
From Derived
Child Constructor.
I'm a Parent Class.
I'm a Child Class.
I'm a Parent Class.
I'm a Child Class.
Because this is an example of polymorphism (late binding). At compile time you specify that the object is of type Parent and therefore can call only methods defined in Parent. But at runtime, when the "binding" happens, the method is called on the object, which is of type Child no matter how it is referenced in the code.
The part that surprises you is why the overriding method should be called at runtime. In Java (unlike C# and C++) all methods are virtual and hence the overriding method is called. See this example to understand the difference.
Both:
child.print();
and
((Parent)child).print();
Should return:
I'm a Parent Class.
I'm a Child Class.
In that order.
Casting an object to its base class doesn't change which method call gets made.
In this case, even after the cast, the child print method gets called and not the parent.
Even though you cast child to Parent this does not change its implementation of the method. This does not actually make it a parent. This is why you can do something like:
Image img = new BufferedImage(...);
Even though Image is abstract img is still a bufferedImage underneath.
Even though you are casting it as the Parent class, that does not mean it will use its parent's functions-- it will only treat the object as a Parent.
By saying ((Parent)child).print(); you are saying "Treat this object as a Parent Object, Not a Child Object". Not "Use the parent method implementations"
Thus if the child object had other methods you wouldn't be able to call them. But since print() is a method of the parent you can still call it, but it uses the actual object's (not the class its casted to) implementation.
in java if we call any method on one object then its calls the method by using sub most object ...............
here:
Object
|
|
Parent
|
|
Child <- sub most object
Case 1::
Child child = new Child();
child.print();
this calling child class method print by using child object... child is sub most
so it prints
output::
I'm a Parent Class.
I'm a Child Class.
Explanation: From child method it is calling parent method because of super.print(); method
so first line is I'm a Parent Class. after completion of parent method execution controls comes back to child method and prints I'm a Child Class.
Case 2::
((Parent)child).print();
if we call like this jvm calls print () method by using sub most object here sub most object is child object so it prints
output::
I'm a Parent Class.
I'm a Child Class.
Explanation: From child method it is calling parent method because of super.print(); method
so first line is I'm a Parent Class. after completion of parent method execution controls comes back to child method and prints I'm a Child Class.