Question regarding result of "No late binding for static methods" [Java] - java

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

Related

Child class private member called from Parent class public member

What is happening in the code below? Please explain the output:
class Parent{
private void fun(){
System.out.println("parent fun\n");
}
public void accessFun(){
System.out.println(this);
this.fun();
}
}
class Child extends Parent{
private void fun(){
System.out.println("child fun");
}
}
class Test{
public static void main(String[] args) {
Child a = new Child();
Parent b = new Parent();
Parent c = new Child();
a.accessFun();
b.accessFun();
c.accessFun();
}
}
Output:
Child#7960847b
parent fun
Parent#3b192d32
parent fun
Child#16f65612
parent fun
Why the line this.fun() is not giving compile-time error?
I think fun is a private member in Child class and therefore can't be accessed from outside the Child class(from public member of it's Parent class).
Why Parent class version of fun() is being called by this.fun()? Note this refers to child class object.
Private members are not inherited.
I think this might be the key point that you are missing here. What this means is that Child.fun does not override Parent.fun. They are just two plain old methods that has nothing to do with each other.
When you call accessFun, control always goes into this bit of code in Parent:
public void accessFun(){
System.out.println(this);
this.fun(); <---- here
}
Now, since we are now inside Parent, we can access fun. And since Parent.fun is not overridden, it calls Parent.fun and not Child.fun.
I think fun is a private member in child class and therefore can't be accessed from outside the class(may even from public member of it's Parent class).
That is a complete misunderstanding. if private members can't be accessed from outside of the class, not even through public methods, then they will be much less useful. Why even have them in the first place?
"Private members can only be accessed by members declared in the same class" is probably a better thing to remember.
private fun() in Parent is called by public accessFun() of same Parent class. And public accessFun() is called in main() of Test class.
Here accessFun() is public so it can be called from any where.
For example just like Pojo classes private members are accessed through public setters and getters
The fun method in parent is private and the child fun() method is not overriding the parent fun() method. But the accessFun method is public so it can be called from the child class and is publicly accessible.
So when you call accessFun() method it will be calling the parent class fun() method. Not the child class fun() method as it is private. That is why you wont get an error.
I think fun is a private member in child class and therefore can't be accessed from outside the class(may even from public member of it's Parent class).
Sometimes everything comes from "outside". The main call comes from outside for example.
If a private member can not be accessed from outside, it would always be dead code and this makes no sense.
The difference is the understanding from direct-access and indirect-access.
In all cases you call the method non-directly via the method accessFun().

Polymorphism: calling subclass' method from superclass' variable

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.

Why this code doesn't call the subclass? Inheritance in Java

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.

Does creating an instance of a child class automatically create its super class object?

If I create an object of sub class then will the super class object also be created from which the sub class is inherited? If not then how by creating a sub class of Thread class (in multi-threading) calls the Thread class constructor and creates a Thread object?
An instance of the subclass is an instance of the superclass. Only one object is created, but as part of that creation, constructor calls are chained together all the way up to java.lang.Object. So for example:
public class Superclass {
// Note: I wouldn't normally use public variables.
// It's just for the sake of the example.
public int superclassField = 10;
public Superclass() {
System.out.println("Superclass constructor");
}
}
public class Subclass extends Superclass {
public int subclassField = 20;
public Subclass() {
super(); // Implicit if you leave it out. Chains to superclass constructor
System.out.println("Subclass constructor");
}
}
...
Subclass x = new Subclass();
System.out.println(x instanceof Subclass);
System.out.println(x instanceof Superclass);
System.out.println(x.superclassField);
System.out.println(x.subclassField);
The output of this is:
Superclass constructor
Subclass constructor
true
true
10
20
... because:
The first thing any constructor does is call either another constructor in the same class, or a superclass constructor. So we see "Superclass constructor" before "Subclass constructor" in the output.
The object we've created is (obviously) an instance of Subclass
The object we've created is also an instance of Superclass
The single object we've created has both fields (superclassField and subclassField). This would be true even if the fields were private (which they usually would be) - the code in Subclass wouldn't be able to access a private field declared in Superclass, but the field would still be there - and still accessible to the code within Superclass.
The fact that we've got a single object with all the state (both superclass and subclass) and all the behaviour (any methods declared within Superclass can still be used on an instance of Subclass, although some may be overridden with more specializd behaviour) is crucial to understanding Java's approach to polymorphism.
Youre only creating one object when you create a subclass of another. It is an instance of both the subclass and all its parents. Example, I create a cat object. It is a cat, and at the same time a feline, mammal, and animal, and an Object.
When you create an object, it gets one piece of memory with one set of variables to hold the all of its data.
The subclass will contain fields from the child and any fields from its ancestors. So it's a single object that acts like the child and its ancestors. There is no parent class object created when you create a subclass.
No there Is only one Object there. There Is a misconception that constructor is for creating an object. But It actually for initializing an object. So when we created child class object along with the child class constructor the parent class constructor also executed because of the first line of the child class constructor either this() or super(). Now, look at the following code.
Public class P{
public P(){
System.out.println(this.hashCode()); // Parent class Constructor
}
}
public class C extends P{
public C(){
System.out.println(this.hashCode()); // Child Class constructor
}
}
public class Test{
public static void main(String [] args){
C c = new C();
System.out.println(c.hashCode());
}
}
If you run the code you can see There is only one HashCode. and an object just has one hashCode. If the parent class object would be created then there must be another hashCode for that object.
Here I am abbreviating with an example that
If a child class object is created, does it automatically create super class object?
class P{
P(){
System.out.println(this.hashCode()); // it will print 2430287
}
}
class C extends P{
C(){
System.out.println(this.hashCode()); // it will also print 2430287
}
}
public class Test{
public static void main(String... args){
C obj = new C();
System.out.println(c.hashCode()); //Again, it will print 2430287
}
}
If you compile and run this code you will find same Object hashCode is getting printed. So, this means there is only one object is created.
Now, how is the parent class object being initialized?
In this example only one object is created which is an instance of the child class, but there are two constructors (parent and child) being executed. But the constructor are just in context of child class only.
Nope.
It will not create instance of parent class. But certainly it will create an instance.And the object reference passed to child class. Hence instance is created at parent class and invoked by child class constructor. and child class methods operates.

Java inheritance

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.

Categories

Resources