I was trying to understand Polymorphism in Java but I could not understand certain things in App.java.
Q1) Why are we able to do p2=tree; even though p2 is reference to class Plant and tree is an object of class Tree?
Q2) Why does it say Type Mismatch:cannot convert from Plant to Tree when I try to do this :
tree=new Plant();
Q3) Why does p2.shed() cause an error even though the output of b2 is true? If p2 is instance of tree it should be able to access Tree methods.
App.java
public class App {
public static void main(String[]args){
Plant p1 = new Plant();;
Plant p2 = p1;
Tree tree = new Tree();
boolean b1= tree instanceof Plant;
p2=tree;
boolean b2= p2 instanceof Tree;
System.out.println(b1+" "+b2);
p2.grow();
tree.shed();
//p2.shed(); ---- Why is this an error?
}
}
Plant.java
public class Plant {
public void grow(){
System.out.println("Plant growing");
}
}
Tree.java
public class Tree extends Plant {
#Override
public void grow() {
System.out.println("Tree growing");
}
public void shed(){
System.out.println("Tree shedding");
}
}
Answers:
1) Plant is the Parent Class of Tree.
I hope you know That when we do Plant p = new Plant(); p is the reference.
And new Plant() is the actual Object.
So,a Parent Reference can point to a child object. So you can do p2=tree or
Plant p2 = new Tree()
2) Now remember the point I wrote above. A Parent Reference can point to a child object. BUT A Child Reference CANNOT point to a Parent Object
i.e you can't do Tree t = new Plant();
3) You cannot do p2.shed() even thought p2 actually points to a Tree object and not Plant object. Because of the Reference restriction.
See the Reference variable "p2" is of Type Plant and is pointing to an object of Tree Type. But the reference p2 doesn't know that it is pointing to an object of Tree type. It thinks that it is pointing to an object of Plant type only.
So when you do p2.grow() It thinks that it is calling the grow() method of Plant class because p2 is a reference of type Plant.
But when when CPU(The executor of your code) goes to the object that p2 is pointing to, CPU finds out that this is actually a Tree object and calls grow() method of Tree and not Plant class and hence it print "Tree is Growing " and not "Plant is growing".
When you do p2.shed() you get Compiler Error. Because in Plant class there is no such method called shed(). Even though the actual object that p2 points to may have a Tree object with shed() method present. The compiling does not happen.
Because the reference (p2) doesn't know about the new method shed() that is present in child object.
Read :: Herbert Schildt - Java A complete reference. The language is very simple.
After you gain some experience in Java read Kathy Sierra SCJP 6 to understand Java in depth.
I'm assuming that you wrote these examples yourself and you understand how using the extends declaration in your classes works. It also looks like you are attempting to extend the class Plant, but it isn't declared as an abstract class. Anyway:
To one of your points, the reason that tree=new Plant(); is throwing an error is because with polymorphism, you have to work from broad to specific.
A Tree is a type of Plant, but a Plant is not a type of Tree, so saying plant = new Tree(); would be valid, which answers your first question.
Lastly, b2 is not true since p2 is a Plant, because as we said before that a Plant is not a type of Tree.
The reason it is giving you an error, however, is that since p2 is of the class Plant (not Tree), it only has one method available, which is grow(), and you are trying to call the shed() method, only available to Trees.
Q1)Why are we able to do p2=tree; even though p2 is reference to class Plant and tree is an object of class Tree?
this is valid
The p1, referencing to a Parent Object, cannot be cast to Child
because a Parent is not a Child. But a Child is a Parent since the
Child inherits all the methods in Parent class. However, if p1 is
referencing to a Child object or a subclass of Child, then you can
cast p1 to Child.
Parent p1=new Parent();
Child c1=new Child();
p1=c1;
Q2) Why does it say Type Mismatch:cannot convert from Plant to Tree when I try to do this : tree=new Plant();
Parent p1=new Parent();
Child c1=new Child();
c1=(Child)p1;
You cannot cast a Child object to its Parent Though it will
compile ,on runtime java identifies that p1 holds a reference which is
not assignment compatiable with c1 and will throw
java.lang.ClassCastException
Q3)Why p2.shed() an error even though the output of b2 is true? If p2 is instance of tree it should be able to access Tree methods.
Reference variable "p2" is of Type Plant and is pointing to an Object
of Tree Type. So it will be able to access the method of Plant class
p2 is defined as Plant and It only can call those methods defined in Plant class, but with the logic of instance Tree. How the method shed is not defined in the Plant class, the variable p2 (of Plant class) not know the method shed, by this it can not call at method shed.
Regards.
Related
If I have super class (Animal) and a sub class (Cat).
What does the third point mean? And when we have to cast?
Cat obj = new Cat(); means creating an object from Cat class
Animal obj = new Animal(); means creating an object from Animal class
Animal obj = new Cat();
First lets understand Class, reference and Object. Suppose we have a class named SomeClass
SomeClass ref = new SomeClass();
Above we have an Object of SomeClass created in Heap and a reference variable refers to it. We have named the reference variable as ref. Object is present in heap and we can just access it using a reference. So Object type is of the actual class (on which new keyword has been applied). Reference variable type can be of actual class or its Parent class.
Now let us see the relationship of Inheritance. A class inheriting from another class share a Child-Parent relationship.
Child inherits the behaviour of its Parent and can then override some of the behaviour and also can add some additional behaviour. Hence Object of Child can be used at any place where Parent object is expected, as Child has all the behaviour of its Parent so invoking any behaviour present in the Parent will be handled by the Child.
Parent class do not know about the additional behaviour of its child class ( child class is written later in time.) Hence object of Parent can not be used at the places where Object of Child is expected (If additional behaviour of Child is invoked on Parent object then it will not be honoured).
Now let us assume we have classes ParentClass and ChildClass such that ChildClass inherits ParentClass
ParentClass reference = new ParentClass(); // Valid
ParentClass reference = new ChildClass(); //Valid
ChildClass reference = new ChildClass(); //Valid
ChildClass reference = new ParentClass();// Not Valid.
Note that
ParentClass reference = new ChildClass(); // Here Object is of type ChildClass and Reference is of type ParentClass.
Now when to cast. Any place expecting the object of ParentClass, there is no need to cast, both the objects (of ParentClass or of ChildClass) are fine.
Any place expecting the Object of type ChildClass but if we have a case like below then casting is needed.
public void someMethod(ChildClass expected){
//some implementation
}
ParentClass ref = new ChildClass();
someMethod(ref);//Invalid : Compilation Issue
someMethod((ChildClass)ref);// Valid
ParentClass anotherRef = new ParentClass();
someMethod(anotherRef); // Invalid : Compilation Issue
someMethod((ChildClass)ref); //Invalid, compiles but Runtime it will fail.
Thumb rule : Child is Child, Child is Parent, Parent is Parent , Parent is not Child.
Another example for understanding.
public abstract class List{
public abstract void add(int element);
public abstract void remove(int element);
public int size();
}
public class Application{
private List listReference;
public void setList(List ref){
listReference = ref;
}
}
//Now you may create sub classes as below
public class ArrayList extends List{
// all the abstract methods of List have been implemented
}
public class LinkedList extends List{
//all the abstract methods of List have been implemented
}
Now in main method you can pass ArrayList or LinkedList or any other implementation.
public class Init{
public static void main(String[] args){
Application app = new Application ();
app.setList(new LinkedList());
//or you can set it like this
List listRef = bew ArrayList();
app.setList(listRef);
//or you can set it like this
LinkedList linkedListRef = new LinkedLiet();
app.setList(linkedListRef);
}
}
Notice that the method setList() accepts List type of reference and we can provide any implementation of the List abstraction. This leads to a flexible design.
Classes should be dependent on the abstraction. Programming to interface is a Design Principle which leads to easy maintenance of the application code.
The reason why this is confusing on the face of it is that it is not something that you would typically do in real code, except in the case of a Factory.
As hinted at in Zabuza's comment, you can do this because a Cat 'is-a' kind of Animal and so you can assign an object of type Cat to an object of type Animal. But you can't do the assignment the other way of course, because an Animal is not a kind of Cat.
Now, there are some lurking issues that come with actually being able to create an instance of the the supertype as well as the subtype that mean you typically wouldn't actually do this in real code because it complicates a lot of things down the road. What you would more likely do is make Animal an interface and have a GenericAnimal class that implements it, along with having Cat implement it.
Say you have an object that represents a zoo, and most zoos typically have a collection of animals. The most obvious way to represent this would be this:
java.util.Collection<com.myproject.Animal> zooAnimals;
So now imagine the zoo builds a new habitat, and it's for a lion. For the sake of the story assume we have a very lazy data model and instead of having a specific com.myproject.animals.cats.Lion subtype we just said "lions are cats, close enough". So to update the data structure that tracks all the animals and their names and addresses and favorite foods and whatever else, we might do this:
com.myproject.Animal newArrival = new com.myproject.animals.Cat("Larry the Lion", "Africa Exhibit", "Gazelles");
zooAnimals.add(newArrival);
Now imagine that the zoo continues to grow, and gets an Ostrich in the Africa habitat. And the same lazy data model applies so we just call it a Bird.
com.myproject.Animal newArrival = new com.myproject.animals.Bird("Oliver the Ostrich", "Africa Exhibit", "Whatever Ostriches Eat");
zooAnimals.add(newArrival);
Now actually writing that exact code would normally only happen in very specific cases inside a factory object or something, and realistically type hierarchies like this have a tendency to not work very well in practice at all, contrary to what a lot of us learned in Object Oriented Programming class, but for the sake of the question that is an example situation where you might do what you are asking about.
Lastly, you also asked when you have to cast. You would have to do this if you had code that needed to know about any special methods or fields that the Cat or Bird types have that Animal does not have. For instance the Cat type might have a property called tailLength because cats typically have tails and for whatever reason the zoo likes to keep track of that. Similarly the Bird type might have a property called wingSpan because birds have wings and we want to keep track of how big they are. The Animal type doesn't have any of these properties so if we get the object for the lion or the ostrich out of the zooAnimals collection (and maybe we looked at the name or something to figure out it was the lion) we would have to cast back to the Cat type in order to access the tailLength property. Same thing for the ostrich and it's wingspan.
for( Animal theAnimal : zooAnimals ){
if( theAnimal.getName().equals("Larry the Lion") ){
Cat theCat = (Cat)theAnimal;
System.out.println("Larry's tail is " + theCat.getTailLength() + " inches long";
}
else if( theAnimal.getName().equals("Oliver the Ostrich") ){
Bird theBird = (Bird)theAnimal;
System.out.println("Oliver's wingspan is " + theBird.getWingSpan() + " inches";
}
}
Again you probably wouldn't actually do something like that in real code, but perhaps it helps to illustrate the example.
A subclass reference-variable cannot refer to superclass:
Child c1 = new Parent(); // Error Incompatible types
So we are telling the compiler i known the type of object:
Parent p1 = new Child();
Child c1 = (Child) p1;
My question is how the Child-class reference variable can point to the super-class object without rising error in run time and if you use casting it changes the state of that type e.g:
int num = (int)6.6; // Result = 6
Something must be happens when p1 object is casted to Child-class.
You're confusing a reference or object with a reference variable, and the difference between the two is a key concept that underlies object-oriented programming principles.
Here:
Parent p1 = new Child();
Child c1 = (Child) p1;
p1 is not a super-class object. Rather it's a super-class variable that refers to a child object in your code. So on the second line, your Child variable, c1 is being assigned a Child object. Note that this code will be allowed by the compiler even if p1 held a super's object, but then the JVM would throw a class cast exception when the code is run.
I am writing a project in Java.
I have a structure where I have instances of objects A, B and C, all of which extend class Parent.
I want to have a list of all objects of type Parent - i.e. I want to store any object of type A, B or C in this list.
I have created a list class with the function
private class Item
{
private Parent parent;
public void addItem(Parent set){ /* adds set to the list */};
}
My original idea was to do something like this:
A a = new A(); B b = new B();
addItem(a);
addItem(b);
But a and b are not Parents they are A and Bs.
Can someone suggest a way of being able to add instances of As, Bs, Cs... to a list of Parents?
I believe what you mean is how do you polymorph an a,b,c to their parent super type? Well, since they subtype the parent type the add method as you defined it should cast your subtype to parent implicitly.
Otherwise how you explicitly refer to the parent type of a subtype is by using a type cast expression... Which is expressed like this:
T_Parent varname = (T_Parent) Name_Subclass;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does the Java cast operator work?
Java casting implementation
I am always wondering how object casting works in Java. I understand for primitive type it will be more like in binary representation level, but what about Object? Is it kind of like Polymorphism or dynamic binding in that everything will be determined at runtime? For example:
class Parent{
void A(){}
}
class Child extends Parent{
#Override
void A(){}
}
Parent p = new Parent();
Child c = (Child) p;
How does this work behind the scene? Does it create a new instance of Child? And also, what happens if you try to cast:
Child b = (Child) new Object();
And last one, when casting a primitive to a wrapper class:
Double d = (Double) 3.3;
I know you don't necessary need to cast it, but what if you do? Is there anything significant that happens on the backend?
No new objects are created in the system when you use explicit casting (except in your last case, where you cast a primitive type to an object wrapper, since double is not an object like Double is). Note that this explicit cast isn't necessary due to Java's autoboxing feature.
In your (Child) new Object() scenario, you will receive a ClassCastException because an Object is not a Child (although the opposite is true).
The answer to your first scenario is the most complicated. Essentially the parent class is treated like an interface might be. When you cast the Child to the Parent, only the Parent API is available. However, the overridden method will still be called. So, if you do:
Parent p = (Parent) new Child();
p.a();
... the Child's public void a() will be called, even though it is being seen through the lens of the Parent class. However if you were to have a second method in the Child that the Parent does not have (let's say public void b() for instance), you would not be able to call that without casting the object back to a Child.
"Behind the scenes", as you say, the only new thing that is created is another object reference which points to the same object. You can have as many references as you like to the same, singular object. Consider this example:
Parent p = new Parent();
Parent p1 = p;
Parent p2 = p;
Parent p3 = p2;
Here, there are four references (p, p1, p2, and p3) each of which points to the same object you created with the new Parent() declaration.
I would probably argue on the philosophical point, though, that this creation of new references is actually explicit rather than behind the scenes when you say Parent p = something.
Links:
http://en.wikipedia.org/wiki/Primitive_wrapper_class
http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
http://docs.oracle.com/javase/7/docs/api/java/lang/ClassCastException.html
http://docs.oracle.com/javase/tutorial/java/IandI/override.html
Is Java "pass-by-reference" or "pass-by-value"?
The simple answer to your main question is No.
All casting happens at syntax checking time.
Casting affects how the syntax checker looks at the object,
it does not affect the object itself, a Child cast to be a
Parent, is still a Child.
However the cast is only checked at Runtime.
Which is why it is dangerous and should not be used
unless there is no other way.
Accodring to this: checkcast, what it does is to verify if the reference is assignable. If it is, the stack is not changed and the operation on that reference are kept.
So if you have:
Child c = ( Child ) anyObject;
c.sayHi();
If the cast success, then the method sayHi could be invoked:
If objectref can be cast to the resolved class, array, or interface type, the operand stack is unchanged; otherwise, the checkcast instruction throws a ClassCastException.
Here's the "bytecode"
$ cat CastDemo.java
class Parent {}
class Child extends Parent {}
class Main {
Child c = (Child) new Parent();
}
$ javap -c Main
Compiled from "CastDemo.java"
class Main {
Child c;
Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class Parent
8: dup
9: invokespecial #3 // Method Parent."<init>":()V
12: checkcast #4 // class Child
15: putfield #5 // Field c:LChild;
18: return
}
First of all, be very careful not to confuse conversion with casting. They may share the surface syntax, but are very different processes.
In Java you can downcast an Object to any type, but at runtime you'll get a ClassCastException if the object is not in fact compatible with the target type. This happens at the bytecode level: there is a bytecode instruction dedicated to downcasting.
Child c = (Child) new Object();
will unconditionally result in a ClassCastException.
Double d = 3.3; // note: no explicit casting needed
will perform autoboxing into an instance of Double. So here, a new instance is actually created.
A normal, successful dowcast may look like this:
Object o = "a";
String s = (String)o;
Here, no objects are created: only the value of o is copied into s. The value is a reference.
Downcasting an object is not doing anything to that object. Behind the scenes the compiler will inject checkcast bytecode operation. If p is not really an instance of Child, exception will be thrown. Otherwise you basically have a (type-)safe reference to the same object with different, more specific type.
Child b = (Child) new Object();
This fails with ClassCastException. JVM compares getClass() of new Object() with Child.class. Since Object.class is not a subclass of Child.class, exception is thrown.
Double d = (Double) 3.3;
Here, casting isn't even necessary, this works as well: Double d = 3.3. Behind the scenes this is translated to:
Double d = Double.valueOf(3.3);
This is known as Autoboxing.
I am new to java and I have some problem on Casting.
I have a class called Parent, and a class called Children, the Children class is the subclass of Parent.
public class Parent
{
int age;
String occupation;
public void print()
{
System.out.println("My age is:"+ age + "and i am a:" + occupation);
}
}
public class Children extends Parent
{
int height;
public static void main(String args[])
{
Children c = new Children();
Parent p = new Parent();
p=c;
c=(Children) p;
/**Here***/
}
}
My problem is, when I add p.XXX after the casting, I only see the age and occupation accessible for instance p. and when I do c.xxx, I see all age, occupation and height accessible.
I thought when I do p=c, p now are considered to be an instance of a children class isn't it? If yes, then why i didnt see the height integer accessible?
And when I do c=(Children)p, an instance of Parent class is assigned to an instance of Children class, and since the Parent instance doesn't have a option, that why we do a casting from parent to children, correct?
I thought when I do p=c, p now are considered to be an instance of a children class isn't it?
No. The type of the variable p is still Parent. The value will be a reference to an instance of Children, but the compiler doesn't take that into account. It only uses the declared type of the variable.
And when I do c=(Children)p, an instance of Parent class is assigned to an instance of Children class, and since the Parent instance doesn't have a option, that why we do a casting from parent to children, correct?
Well you're not changing the instance at all. You're casting an expression of type Parent - the value will be a reference. At execution time, the JVM will ensure that the value is actually a reference to an instance of Children or some subtype (or null) - if it isn't, the JVM will throw an exception.
It's very important to distinguish between variables, references and objects - they're three quite different concepts, and making sure you understand the difference between them will make a lot of other things clearer.