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.
Related
Here is what JavaDoc says:
public final Class <?> getClass()
Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.
The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. For example, no cast is required in this code fragment:
Number n = 0;
Class<? extends Number> c = n.getClass();
Returns:
The Class object that represents the runtime class of this object.
Now , I understand it is a native method , so it is is implemented in platform-dependent code. But what about the return type of this method.
public final Class<?> getClass()
Also , consider the code:
class Dog
{
#Override
public String toString()
{
return "cat";
}
}
public class Main
{
public static void main(String[] args)
{
Dog d= new Dog();
//Class<Dog> dd = new Dog(); Compile time error
System.out.println(d.getClass());
}
}
Output:
class Dog
So, my query lies in :
Return type of this method
toString method is not called . A similar post on this topic is :
Java. getClass() returns a class, how come I can get a string too?
The commented code which otherwise give compile time error.
The data for each object contains a reference to an object of class java.lang.Class, and this is returned by the method getClass. There is also one java.lang.Class object describing java.lang.Class.
Think of a Class object as the "blueprint" describing a certain class from which objects are being made. It stands to reason that blueprints also need a blueprint of their own (or else how would engineers know how to make blueprints).
These statements try to illustrate this.
Integer integer = 1;
Class<?> clazzInteger = integer.getClass();
System.out.println( "class of integer=" + clazzInteger );
Class<?> clazzClazzInteger = clazzInteger.getClass();
System.out.println( "class of class Integer's class=" + clazzClazzInteger );
String string = "x";
Class<?> clazzString = string.getClass();
System.out.println( "class of string=" + clazzString );
Class<?> clazzClazzString = clazzString.getClass();
System.out.println( "class of class String's class=" + clazzClazzString );
Output:
class of integer=class java.lang.Integer
class of class Integer's class=class java.lang.Class
class of string=class java.lang.String
class of class String's class=class java.lang.Class
A class has a name, just like anything described by a blueprint has a name which is not to be confused with the blueprint itself. If a class object appears in a certain context, its toString() method is called implicitly, and this returns the class' name. If you'd like to print all the nitty-gritty details of a class (akin to printing the blueprint itself) you'd have to write a lot of code - just look at the javadoc for java.lang.Class: there's an awful lot of information to be retrieved (as befits a blueprint).
At this point, we need to differentiate between a type and an instance of the type. Lets explain it with an example.
public class A {
public static void main(String[] args) {
Class<A> typeInformation = A.class; //Type information associated with type `A`
A instanceOfA = new A(); //actual instance of type `A`
}
}
Type
The reference 'typeInformation' in the above code is of the type Class keeping aside the generics for a while. This information will typically be residing in non-heap memory section. Following information is store against each of the type jvm loads :
The fully qualified name of the type
The fully qualified name of the type's direct superclass (unless the type is an interface or class java.lang.Object, neither of which have a superclass)
Whether or not the type is a class or an interface
The type's modifiers ( some subset of` public, abstract, final)
An ordered list of the fully qualified names of any direct superinterfaces
Instance
instaneOfA is a reference to the actual instance of the type A which points to an address in the heap memory.
Return type of getClass() is a generic Class type. Like many other types available in java - String, Integer etc, Class is also a type representing the type information associated.
toString() method is associated and invoked on an instance of the Dog class, not on the Dog type itself.
//Class<Dog> dd = new Dog(); Compile time error
This is due to Type mismatch occuring while assigning the result of expression in the right hand side to the Left Hand Side, which is not of the same type.
Class dd refers to a reference of Class type.
Dog is a different type altogether, and a new Dog() can be assigned to a reference of the type 'Dog'.
This link will help you understand the design aspects of java runtime environment
I have an answer for your Question 3,
This gives compile time error because
Reason 1: For a Class instance, You can only assign class object that represents the Dog class, but you can't assign the Dog class object directly.
For example: Class dd=Dog.class or Class dd=Class.forName("Dog");
is correct syntax.
Reason 2: The class Class is a final class but not a super class for Dog class. You go back to the concept of dynamic method dispatch in java,where you can only assign subclass objects to a superclass variable.
class Animal{
public void findAnimal(){
System.out.println("Animal class");
}
public void sayBye(){
System.out.println("Good bye");
}
}
class Dog extends Animal{
public void findAnimal(){
System.out.println("Dog class");
}
}
Given the inheritance above ,it is understood that a reference of Animal can refer to an object of Dog
Animal animal=new Dog();
As a Dog object can perform everything an Animal can do like in above case a Dog also have sayBye and findAnimal methods.
But why it is allowed to downcast an Animal object to a Dog object which serves no purpose and fails at runtime.
Dog dog=(Dog)new Animal(); // fails at runtime but complies.
Dog dog=(Dog)animal;
The above statement look logical as the animal reference is pointing to a Dog object.
This sort of casting is allowed for situations when you get an object of a superclass from outside code, e.g. as a parameter to your method, and then you need to call methods specific to a subclass.
This is not a good practice, but in some rare situations you are forced to do things like that, so the language allows it:
void sound(Animal animal) {
if (animal instanceof Dog) {
Dog dog = (Dog)animal();
dog.bark();
}
if (animal instanceof Cat) {
Cat cat = (Cat)animal();
cat.meow();
}
}
why it is allowed to compile Dog dog=(Dog) new Animal()
Because compiler designers decided to not detect this error at compile time. They verified that the expression being cast to Dog is of type that is a superclass of Dog, and allowed the expression to compile. They could go further and check that the expression will always result in an exception, but that would require an additional effort for very little improvement in user experience with the language.
Because you need it sometimes.
Especially when Java did not yet have generics (Java 1.4 and older), you almost always needed to cast when you got for example an object out of a collection.
// No generics, you don't know what kinds of objects are in this list
List list = new ArrayList();
list.add(new Dog());
// Need to cast because the return type of list.get() is Object
Dog dog = (Dog)list.get(0);
Since we have generics since Java 5, the need for casting is greatly reduced.
You should try to avoid casting in your code as much as possible. A cast is a way to deliberately switch off the compiler's type checking - in general you don't want to do that, you want to make use of the compiler's checking instead of circumventing it. So, if you have code where you need to cast, think a bit further to see if you can write it without the cast.
You need that capability to access an earlier cast object as its original type.
For example, if you cast a Dog to an Animal to pass it to a generic processor, you may later need to cast it back to a Dog to perform specific methods.
The developer is responsible to make sure the type is compatible - and when it is there will be no error. Some pseudo code:
public void example(Animal foo){
if( ...condition... ) ((Dog)foo).bark();
else if( ...other condition... ) ((Cat)foo).meow();
}
Since the introduction of generics, this is less commonly used, but there are still cases for it. The developer is solely responsible for guaranteeing the type is right if you don't want an error.
case 1 -
Here we use loose coupling.
Animal animal = getSomeDog(),
Dog dog = (Dog) animal; // this is allowed because animal could reference a dog
case 2
Here we you use tight coupling.
Animal animal = new Animal();
Dog dog = (Dog) animal; // this will fail at runtime, because animal doesn't reference a Dog
We use Downcasting when there is possibility to succeed at run time
so case 1 has possibility to succeed at runtime over case 2
Down casting is considered as a bad Object Oriented practice. It must be avoided to as much extent as possible.
Java still has it and your question is a good question as why Java allows Down-casting.
Suppose a case below.
public interface List{
public boolean add(Object e);
public boolean remove(Object o);
}
public class ArrayList implements List{
// Extra method present in the ArrayList and not in the parent Interface
public Object[] toArray() {
// returns array of the objects
return Arrays.copyOf(elementData, size);
}
#Override
public boolean add(Object e){
// add e to the ArrayList Underlying array
}
#Override
public boolean remove(Object o){
// remove o from the ArrayList Underlying array
}
}
A good Object oriented practice is to Code for Interfaces. But often there are methods defined in the concrete implementations which we need to call. I read an comment from some one and I quote it in my words.
Know the Rules, in case you need to break them Do break them Knowingly and take care so as to prevent from any adverse effect.
Below is an example where we need to do the Down-casting. The example of down-casting in your question is to teach what is down-casting, below is real life example.
public void processList(List items){
items.add( new Object() );
items.add( new Object() );
processAsPerTypeOfList(items);
}
public void processAsPerTypeOfList( List items ){
if( items instanceof ArrayList){
Object[] itemArray = ((ArrayList)items).toArray();// DOWNCASTING
// Process itemArray
}
}
For more reference you can also see a related question : Why Java needs explicit downcasting?
I have come across this example on http://www.javabeginner.com/learn-java/java-object-typecasting and in the part where it talks about explicit type casting there is one example which confuses me.
The example:
class Vehicle {
String name;
Vehicle() {
name = "Vehicle";
}
}
class HeavyVehicle extends Vehicle {
HeavyVehicle() {
name = "HeavyVehicle";
}
}
class Truck extends HeavyVehicle {
Truck() {
name = "Truck";
}
}
class LightVehicle extends Vehicle {
LightVehicle() {
name = "LightVehicle";
}
}
public class InstanceOfExample {
static boolean result;
static HeavyVehicle hV = new HeavyVehicle();
static Truck T = new Truck();
static HeavyVehicle hv2 = null;
public static void main(String[] args) {
result = hV instanceof HeavyVehicle;
System.out.print("hV is an HeavyVehicle: " + result + "\n");
result = T instanceof HeavyVehicle;
System.out.print("T is an HeavyVehicle: " + result + "\n");
result = hV instanceof Truck;
System.out.print("hV is a Truck: " + result + "\n");
result = hv2 instanceof HeavyVehicle;
System.out.print("hv2 is an HeavyVehicle: " + result + "\n");
hV = T; //Sucessful Cast form child to parent
T = (Truck) hV; //Sucessful Explicit Cast form parent to child
}
}
In the last line where T is assigned the reference hV and typecast as (Truck), why does it say in the comment that this is a Successful Explicit Cast from parent to child? As I understand casting (implicit or explicit) will only change the declared type of object, not the actual type (which shouldn't ever change, unless you actually assign a new class instance to that object's field reference). If hv was already assigned an instance of a HeavyVehicle class which is a super class of the Truck class, how can then this field be type cast into a more specific subclass called Truck which extends from the HeavyVehicle class?
The way I understand it is that casting serves the purpose of limiting access to certain methods of an object (class instance). Therefore you can't cast an object as a more specific class which has more methods then the object's actual assigned class. That means that the object can only be cast as a superclass or the same class as the class from which it was actually instantiated. Is this correct or am I wrong here? I am still learning so I am not sure if this is the correct way of looking at things.
I also understand that this should be an example of downcasting, but I am not sure how this actually works if the actual type doesn't have the methods of the class to which this object is being downcasted. Does explicit casting somehow change the actual type of object (not just the declared type), so that this object is no longer an instance of HeavyVehicle class but now becomes an instance of Truck class?
Reference vs Object vs Types
The key, for me, is understanding the difference between an object and its references, or put in other words the difference between an object and its types.
When we create an object in Java, we declare its true nature, which will never change (e.g. new Truck()). But any given object in Java is likely to have multiple types. Some of these types are obviously given by the class hierarchy, others are not so obvious (i.e. generics, arrays).
Specifically for reference types, the class hierarchy dictates the subtyping rules. For instance in your example all trucks are heavy vehicles, and all heavy vehicles are vehicles. Therefore, this hierarchy of is-a relationships dictates that a truck has multiple compatible types.
When we create a Truck, we define a "reference" to get access to it. This reference must have one of those compatible types.
Truck t = new Truck(); //or
HeavyVehicle hv = new Truck(); //or
Vehicle h = new Truck() //or
Object o = new Truck();
So the key point here is the realization that the reference to the object is not the object itself. The nature of the object being created is never going to change. But we can use different kinds of compatible references to gain access to the object. This is one of the features of polymorphism here. The same object may be accessed through references of different "compatible" types.
When we do any kind of casting, we are simply assuming the nature of this compatibility between different types of references.
Upcasting or Widening Reference Conversion
Now, having a reference of type Truck, we can easily conclude that it's always compatible with a reference of type Vehicle, because all Trucks are Vehicles. Therefore, we could upcast the reference, without using an explicit cast.
Truck t = new Truck();
Vehicle v = t;
It is also called a widening reference conversion, basically because as you go up in the type hierarchy, the type gets more general.
You could use an explicit cast here if you wanted, but it would be unnecessary. We can see that the actual object being referenced by t and v is the same. It is, and will always be a Truck.
Downcasting or Narrowing Reference Conversion
Now, having a reference of type Vechicle we cannot "safely" conclude that it actually references a Truck. After all it may also reference some other form of Vehicle. For instance
Vehicle v = new Sedan(); //a light vehicle
If you find the v reference somewhere in your code without knowing to which specific object it is referencing, you cannot "safely" argument whether it points to a Truck or to a Sedan or any other kind of vehicle.
The compiler knows well that it cannot give any guarantees about the true nature of the object being referenced. But the programmer, by reading the code, may be sure of what s/he is doing. Like in the case above, you can clearly see that Vehicle v is referencing a Sedan.
In those cases, we can do a downcast. We call it that way because we are going down the type hierarchy. We also call this a narrowing reference conversion. We could say
Sedan s = (Sedan) v;
This always requires an explicit cast, because the compiler cannot be sure this is safe and that's why this is like asking the programmer, "are you sure of what you are doing?". If you lie to the compiler you will throw you a ClassCastException at run time, when this code is executed.
Other Kinds of Subtyping Rules
There are other rules of subtyping in Java. For instance, there is also a concept called numeric promotion that automatically coerce numbers in expressions. Like in
double d = 5 + 6.0;
In this case an expression composed of two different types, integer and double, upcasts/coerces the integer to a double before evaluating the expression, resulting in a double value.
You may also do primitive upcasting and downcasting. As in
int a = 10;
double b = a; //upcasting
int c = (int) b; //downcasting
In these cases, an explicit cast is required when information can be lost.
Some subtyping rules may not be so evident, like in the cases of arrays. For instance, all reference arrays are subtypes of Object[], but primitive arrays are not.
And in the case of generics, particularly with the use of wildcards like super and extends, things get even more complicated. Like in
List<Integer> a = new ArrayList<>();
List<? extends Number> b = a;
List<Object> c = new ArrayList<>();
List<? super Number> d = c;
Where the type of a is a subtype of the type of b. And the type of c is a subtype of the type of d.
Using covariance, wherever List<? extends Number> appears you can pass a List<Integer>, therefore List<Integer> is a subtype of List<? extends Number>.
Contravariance produce a similar effect and wherever the type List<? super Number> appears, you could pass a List<Object>, which makes of List<Object> a subtype of List<? super Number>.
And also boxing and unboxing are subject to some casting rules (yet again this is also some form of coercion in my opinion).
You got it right. You can successfully cast an object only to its class, some of its parent classes or to some interface it or its parents implement. If you casted it to some of the parent classes or interfaces, you can cast it back to the original type.
Otherwise (while you can have it in source), it will result in a runtime ClassCastException.
Casting is typically used to make it possible to store different things (of the same interface or parent class, eg. all your cars) in the same field or a collection of the same type (eg. Vehicle), so that you can work with them the same way.
If you then want to get the full access, you can cast them back (eg. Vehicle to Truck)
In the example, I am pretty sure that the last statement is invalid and the comment is simply wrong.
When you make a cast from a Truck object to a HeavyVehicle like that:
Truck truck = new Truck()
HeavyVehicle hv = truck;
The object is still a truck, but you only have access to heavyVehicle methods and fields using the HeavyVehicle reference. If you downcast to a truck again, you can use again all the truck methods and fields.
Truck truck = new Truck()
HeavyVehicle hv = truck;
Truck anotherTruckReference = (Truck) hv; // Explicit Cast is needed here
If the actual object you are downcasting is not a truck, a ClassCastException will be throw like in the following example:
HeavyVehicle hv = new HeavyVehicle();
Truck tr = (Truck) hv; // This code compiles but will throw a ClasscastException
The exception is thrown because the actual object is not of the correct class, its an object of a superclass (HeavyVehicle)
The last line of code compiles and runs successfully with no exceptions. What it does is perfectly legal.
hV initially refers to an object of type HeavyVehicle (let's call this object h1):
static HeavyVehicle hV = new HeavyVehicle(); // hV now refers to h1.
Later, we make hV refer to a different object, of type Truck (let's call this object t1):
hV = T; // hV now refers to t1.
Lastly, we make T refer to t1.
T = (Truck) hV; // T now refers to t1.
T already referred to t1, so this statement didn't change anything.
If hv was already assigned an instance of a HeavyVehicle class which is a super class of the Truck class, how can then this field be type cast into a more specific subclass called Truck which extends from the HeavyVehicle class?
By the time we reach the last line, hV no longer refers to an instance of HeavyVehicle. It refers to an instance of Truck. Casting an instance of Truck to type Truck is no problem.
That means that the object can only be cast as a superclass or the same class as the class from which it was actually instantiated. Is this correct or am I wrong here?
Basically, yes, but don't confuse the object itself with a variable that refers to the object. See below.
Does explicit casting somehow change the actual type of object (not just the declared type), so that this object is no longer an instance of HeavyVehicle class but now becomes an instance of Truck class?
No. An object, once created, can never change its type. It can't become an instance of another class.
To reiterate, nothing changed on the last line. T referred to t1 before that line and it refers to t1 afterward.
So why is the explicit cast (Truck) necessary on the last line? We are basically helping just helping out the compiler.
We know that by that point, hV refers to an object of type Truck, so it's ok to assign that object of type Truck to the variable T. But the compiler isn't smart enough to know that. The compiler wants our assurance that when it gets to that line and tries to make the assignment, it will find an instance of Truck waiting for it.
The above code will compile and run fine. Now change above code and add following line
System.out.println(T.name);
This will make sure that you are not using the object T after downcasting hV object as Truck.
Currently, in your code you are not using T after downcast so everything is fine and working.
This is because, by explicitly cast hV as Truck, complier does complain considering that programmer as casted the object and is aware of the what object is been casted to what.
But at runtime JVM is not able to justify the casting and throws ClassCastException "HeavyVehicle cannot be cast to Truck".
To help better illustrate some points made above, I modified the code in question and add more codes to it with inline comments (including actual outputs) as follows:
class Vehicle {
String name;
Vehicle() {
name = "Vehicle";
}
}
class HeavyVehicle extends Vehicle {
HeavyVehicle() {
name = "HeavyVehicle";
}
}
class Truck extends HeavyVehicle {
Truck() {
name = "Truck";
}
}
class LightVehicle extends Vehicle {
LightVehicle() {
name = "LightVehicle";
}
}
public class InstanceOfExample {
static boolean result;
static HeavyVehicle hV = new HeavyVehicle();
static Truck T = new Truck();
static HeavyVehicle hv2 = null;
public static void main(String[] args) {
result = hV instanceof HeavyVehicle;
System.out.print("hV is a HeavyVehicle: " + result + "\n"); // true
result = T instanceof HeavyVehicle;
System.out.print("T is a HeavyVehicle: " + result + "\n"); // true
// But the following is in error.
// T = hV; // error - HeavyVehicle cannot be converted to Truck because all hV's are not trucks.
result = hV instanceof Truck;
System.out.print("hV is a Truck: " + result + "\n"); // false
hV = T; // Sucessful Cast form child to parent.
result = hV instanceof Truck; // This only means that hV now points to a Truck object.
System.out.print("hV is a Truck: " + result + "\n"); // true
T = (Truck) hV; // Sucessful Explicit Cast form parent to child. Now T points to both HeavyVehicle and Truck.
// And also hV points to both Truck and HeavyVehicle. Check the following codes and results.
result = hV instanceof Truck;
System.out.print("hV is a Truck: " + result + "\n"); // true
result = hV instanceof HeavyVehicle;
System.out.print("hV is a HeavyVehicle: " + result + "\n"); // true
result = hV instanceof HeavyVehicle;
System.out.print("hV is a HeavyVehicle: " + result + "\n"); // true
result = hv2 instanceof HeavyVehicle;
System.out.print("hv2 is a HeavyVehicle: " + result + "\n"); // false
}
}
I can't get a clear idea about inheritance in Java. For instance, I have:
class A
{
...
public void MethodA();
}
Here is everything is clear. Then I want a (sub)class:
class B extends A
{
...
public void MethodB();
}
Then I create an instance of A. Then I want to get an instance of B having all the stuff from A. I want to make something like aA = new B(); but get an error.
Using this thing is not really comfortable:
A aA = new A(...);
B aB = new B(null,null,...);
aB = aA
How should I make it correctly and get a clear idea about inheritance in Java?
UPD: So how can i get an instance of B having all the stuff of A?
It sounds like you want an instance of B in the first place. Once you have such an instance, you can use it whenever either A or B is required.
Put another way, every instance of B is automatically also an instance of A.
This is called the Liskov Substitution Principle.
In your example, A - superclass, B - subclass.
A subclass possesses all the attributes and operations of its superclass (because a subclass inherited all attributes and operations from its superclass). This means that a subclass object can do whatever its superclass can do. As a result, we can substitute a subclass instance when a superclass instance is expected, and everything shall work fine. This is called substitutability.
You need to understand the IS-A relationship. Let's discuss an example of Employee and Manager relationship.
class Employee{
public Employee(){
System.out.println("Employee obj");
}
}
class Manager extends Employee{
public Manager(){
System.out.println("Manager obj");
}
}
By extending Employee we are declaring Manager as a specialization of Employee. Therefore, every Manager is an Employee but every Employee is not Manager.
A reference of type Employee can refer to the objects who satisfy the IS-A relationship. Therefore, these are perfectly legal to write:
Employee emp1 = new Employee();
Employee emp2 = new Manager();
However, if we try to write
Manager man1 = new Employee(); //Wrong: Compilation error.
This violates the IS-A relationship. As a result of this we get compile time error. In order to avoid this kind of compilation error we need to add a cast to type Manager. But, casting to type Manager only avoids compilation issues. You will get a java.lang.ClassCastException as a result of of this kind of casting.
Manager man1 = (Manager) new Employee(); //Wrong: avoids compilation error but will generate a ClassCastException at runtime.
I suggest you to go through the Java Language Specification: Section 5.5.1 to get a full idea of casting a reference type.
Every instance of B has all of stuff from A, because it is an A. But it seems like you actually want to create an instance of B from a given instance of A. This isn't possible, unless you specifically write your class so as to allow it:
public class B extends A {
public B(A original) { ... }
}
and later
A a = new A();
B b = new B(a);
I have many sub-classes implementing the superclass Animal (Dog, Cat, Mouse, etc)
So I do:
Animal[] arrayOfAnimals = new Animal[100];
I put in it Dog,Cat etc objects.
When I get something from it I do
If(arrayOfAnimals[1] instanceof Dog) {
((Dog)(arrayOfAnimals[1])).speak();
}
else if(arrayOfAnimals[1] instanceof Cat) {
((Cat)(arrayOfAnimals[1])).speak();
}
Because I need to know if that Animal is a Cat or a Dog because,for example, each one speaks differently.
Now assuming I have many subclasses of Animals, I will consecutively get many "else if..."
My question is: Is there a way to avoid this? I have already tried using an interface (Animal -> interface, Dog,Cat etc implementing animal), but in my project an array has to be cloneable, and you can't clone an array "Animal [] arrayOfAnimals" if Animal is an interface (objects inside that array will not be cloned)
Because i need to know if that Animal is a Cat or a Dog because,for example, each one speaks differently.
That sounds like it's an implementation detail - if every animal can speak in some form, you should put the speak() method into Animal as an abstract method. Each subclass will then override it to provide the implementation. Then you can just use
arrayOfAnimals[1].speak();
... and polymorphism will take care of using the right implementation.
You can clone an array of an interface type, btw:
interface Foo {
}
class FooImpl implements Foo {
}
public class Test {
public static void main(String[] args) {
Foo[] foos = { new FooImpl() };
Foo[] clone = (Foo[]) foos.clone();
System.out.println(foos[0] == clone[0]); // true
}
}
Note that regardless of the type involved, calling clone() on array won't clone each element - the new array will contain the same references as the old array. It's a shallow copy. If you want to do that, you'll have to code it yourself (or find a third party library).
Why don't you move speak() to the superclass and let the subclasses override it?