Why am I able to access child methods in the parent class? - java

I have a problem with the understanding of inheritance in Java: I am able to access overwritten methods of the child class when I cast it back to the parent class.
As an Example there are given the two following classes:
The parent one:
public class Parent {
public void whatAreYou() {
System.out.println("parent");
}
}
And a child class:
public class Child extends Parent {
#Override
public void whatAreYou() {
System.out.println("child");
}
public void onlyChildrenCanDoThis() {
//...
}
}
When I now do the following:
Child c = new Child();
Parent p = c;
p.whatAreYou();
I get this output:
child
This is very strange for my understanding of inheritance in Java. I would expect to get a parent output, because I narrowed the child class to the parent class, and with that I should just have access to variables and methods of the parent class.
This is working with p.onlyChildrenCanDoThis(), as I cannot access it, because it is not implemented in the parent class...
...but with overwritten methods Java is not behaving that way! Why is that?

What you are dealing with here is polymorphism. c is instantiated as new child(), and that is why you get child as an output. The fact that p is of type parent doesn't change that fact, it still points to the instance of child.

Here's what you have done
child c = new child();
You created Object of Child class and assigned its reference to c.
parent p = c;
Here you have copied reference of child object to p. Remember the object is still Child's object not parents's object.
p.whatAreYou();
Here you have called whatAreYou method. you are calling this using reference variable p which is pointing to object of child. hence child's method will be called.
Another Interpretation

The output is as it is because of the line parent p = c;
Imagine this:
class Car {
public void whatAreYou() {
System.out.println("Car");
}
}
class Cadillac extends Car {
public void whatAreYou() {
System.out.println("Caddillac");
}
}
If you now say
Cadillac coolCar = new Cadillac();
Car testCar = coolCar;
testCar.whatAreYou();
It becomes pretty obvious that the output is, "Cadillac", no? This is how you can look at inheritence:
Cadillac objects are allways Cars. Car objects can be Cadillacs
Since I explicitly set the Cadillac reference coolCar to point to an object of a Cadillac, and the Car reference testCarto point to the same object, we get the output "Cadillac"
To make it even more obvious, you could even say
Car coolCar = new Cadillac();
Car testCar = coolCar;
testCar.whatAreYou();

Related

Converting Class of an Object into a Child Class

Say I have the following classes
public abstract class Parent {
public Parent() {
//stuff here
}
}
public class Child extends Parent {
public Child() {
//stuff here
}
public void doSomething() {
}
}
Then I get an object from an array of Parents
public Parent[] parents = new Parent[5];
Parent tempParent = parents[0]
If this object is of the child class, I want to cast the tempParent into the child class in order to use "doSomething" without having to create a new object
if(tempParent.getClass == Child.class) {
tempParent = (Child) tempParent;
tempParent.doSomething();
}
This, however, does not work. I still get an error telling me that doSomething is not a function in the Parent class. Is there a way to do what I'm trying to do?
You need to use the correct TYPE on the LEFT hand side:
Child someChild = (Child) tempParent;
Note: this does not create a new Object.
There is no way of having
Parent whatever = (Child) tempParent;
do what you want to do (invoke a Child class method)!
You see, the compiler only cares about the "defined" type of your reference, it does not take into account that you most likely, at runtime, just "put" something into that reference that in deed is a Child instance!
to do what you want to do.
And note: do not compare objects using ==. You should prefer to call equals() instead. For Class objects == should work (most of the time), but still: get used to check for equality using equals().
I think you're trying to solve the issue from the wrong side.
Technically speaking you should do it like this.
public abstract class Parent {
public Parent() {
//stuff here
}
public abstract void doSomething();
}
public class Child extends Parent {
public Child() {
//stuff here
}
#Override
public void doSomething() {
// Write the code of doSomething specific to child.
}
}
A bit off topic but you might want to consider the following:
I think that the class representation of your code is bad.
I think that you should have 2 concrete classes Parent and Child that are composed or either inherit from a common interface. Even better use composition over inheritance.
https://en.wikipedia.org/wiki/Composition_over_inheritance
if you are able to modify the parent class, I would recommend that you make doSomething an abstract method and have the child class override it. that way, there is no need to cast in order to invoke it.
https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

Assigning a parent class to a variable of child type [duplicate]

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.

Inheritance Example in java

In the example below :
class Parent{
void fun() {
System.out.println("Parent class");
}
}
class Child extends Parent{
}
public class Main {
public static void main(String[] ar) {
Child ch = new Child();
ch.fun();
}
}
inheritance example,while instantiating object,we can create an object as Parent ch = new Child(); which is valid but why can't we have something like this Child ch = new Parent();
Thanks in advance.
Child ch = new Parent() is invalid because not every Parent is a Child.
Suppose you had a third class:
class AnotherChild extends Parent {int age = 2;}
The following would also be valid:
Parent otherChild = new AnotherChild();
If Cild child = new Parent() were to be made valid, then for the same reason
Child child = new AnotherChild()
Would also have to be made valid because AnotherChild is a Parent.
Now clearly, that is problematic, because Child is different from AnotherChild.
This example is chosen to make it obvious, but even a simple Parent object (new Parent()) is not a Child instance, because it wasn't instantiated with the Child class or any of its sub-classes.
All this is compile-time type checks, which ensures code safety and object/variable compatibility. One can use allowed casts to go around the problem, but if runtime objects are in fact of incompatible types, the execution would still fail.
In your example you have class Child extends Parent{. This means that a Child is a Parent but Parent is not a Child. Parent is the more generic parent class (Ironic) and Child is the more specific sub class. So you can do something like this:
Parent ch = new Child();
Because you are declaring the generic Parent object, and then instantiating it as a Child object. However you cannot do:
Child ch = new Parent();
Because you cannot declare it as the more specific Child object and then instantiate it as the less specific Parent object

How inheritance works indeed?

Please help me to understand how inheritance works.
If I have two classes, parent and child. When I create an instance of child is parent class instance constructed as well or not?
My code of Parent class.
public class Parent {
private char s;
#Override
public int hashCode() {
return s;
}
}
And Child
public class Child extends Parent {
private int i;
public Child(int i) {
super();
this.i = i;
}
#Override
public int hashCode() {
return i;
}
}
And finally the test
public class Main {
public static void main(String[] args) {
Child child = new Child(100);
System.out.println(child.hashCode());
System.out.println(child.getClass().getSuperclass().hashCode());
}
}
In output I get
100
2000502626
So the hashes of objects are different. It means that when I create instance of Child it is also created instance of Parent. Am I right?
Your question has nothing to do with inheritance.
the 100 you get from child instance's hashcode() method, as you expected.
The 2000502626 was from Parent.class, not Parent object.
Parent.class has type java.lang.Class
parent object has type Parent
When you create a Child object a Parent constructor is invoked as well, because a Child is a Parent.
But when you do this:
System.out.println(child.getClass().getSuperclass().hashCode());
you're not invoking Parents instance hashode. You are invoking hashCode() of the instance of the Class object.
See what child.getClass().getSuperclass() returns. It returns an instance of type Class not of type Parent/Child.
You cannot invoke Parents instance methods using child.getClass().getSuperClass() - that doesn't return the instance of a type, but an object representing this type.
Try doing this in child method:
#Override
public int hashCode() {
System.out.println("In child hashCode: " + i);
System.out.println("Parents hashCode: " + super.hashCode());
return i;
}
This will return 100 and 0, as Parents s hasn't been initialized.
Actually, there will be just one child object created. Since every child is a parent, the parent constructor will be invoked. if you print this in both child as well as parent instance methods, it will print the same (child object)
check - this question
If I have two classes, parent and child, When I create an instance of child is parent class instance constructed as well or not?
Yes. It works through Constructor. When you call constructor of your child class to create object, it first calls its parent class contructor and hence creates object of parent class
Yes. Both parent and child object are created. The child class constructor calls the parent(super) class constructor first, then only other functions of the child class are performed. As you can see from your own code two different values getting printed.

Calling a child's methods where the defined reference type belongs to parent but the actual reference is a child object

I have a parent, and a child class,
class Parent
{
// variables
// constructor
}
class Child extends Parent
{
// variables
// constructor
public void AChildMethod()
{
// do something
}
}
And inside my program, I have a reference of the main type, but it references to a child type
Parent obj = new Child();
Is it possible to call the "AChildMethod" method of the child in a way like this?
obj.AChildMethod();
Thank you very much in advance.
You can check whether it really is an instance of the Child class, and then simply cast to the child type:
if ( obj instanceof Child ) {
((Child) obj).aChildMethod();
// or
Child childObj = (Child) obj;
childObj.aChildMethod();
}
However, if a cast like this is needed, it could be an indication that your class hierarchy should be improved.
If you know that obj is actually a Child, then you can cast it to a Child and then call childMethod. That's the only way to do it.

Categories

Resources