Upcasting is automatical, but downcasting is manual
Code:
Cat c1 = new Cat();
Animal a = c1; //automatic upcasting to Animal
Cat c2 = (Cat) a; //manual downcasting back to a Cat
Because upcasting can never fail, because of inheritance. But if you have a group of different animals like dog and cat and so on, and want to downcast them to a Cat, then there's a chance, that some of these Animals are actually Dogs, and you want to downcast them to Cats, and process fails, by throwing ClassCastException. And we use a useful feature called "instanceof" to test if an object is instance of some Class.
Code:
Cat c1 = new Cat();
Animal a = c1; //upcasting to Animal
if(a instanceof Cat){ // testing if the Animal is a Cat
System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");
Cat c2 = (Cat)a;
}
If you upcast an object, it will lose all its properties, which were inherited from below its current position. For example, if you cast a Cat to an Animal, it will lose properties inherited from Mammal and Cat. Note, that data will not be lost, you just can't use it, until you downcast the object to the right level.
The beauty of casting is that programmer can make general methods. Like the methods in the Animal Class, or the methods with the input Animal. These methods can be used by all their subclasses. For example, public static void stroke(Animal a) { System.out.println(" you stroke the " + a); }. And the Cat c and Dog d can use this method like, stroke(c) and stroke(d).
"I really need to make a Dog out of my Cat!"
Well, you can't do it by casting. However, objects are nothing else, but few methods and fields. That means, you can make a new dog out of your Cat's data.
Let's say you have a Cat class:
Code:
class Cat extends Mammal {
Color furColor;
int numberOfLives;
int speed;
int balance;
int kittens = 0;
Cat(Color f, int n, int s, int b){
this.furColor = f;
this.numberOfLives = n;
this.speed = s;
this.balance = b;
}
}
and a Dog class.
Code:
class Dog extends Mammal {
Color furColor;
int speed;
int barkVolume;
int puppies = 0;
Dog(Color f, int n, int s, int b){
this.furColor = f;
this.speed = s;
this.barkVolume = b;
}
}
and you want to make a Dog out of the Cat. All you need to do, is, place a method inside of the Cat class, that converts the fields and returns a new Dog based on that.
Code:
public Dog toDog(int barkVolume){
Dog d = new Dog(furColor, speed, barkVolume);
d.puppies = kittens;
return d;
}
As you can see, they don't match that well, so some fields were inconvertible, and some data had to be made from scratch. Notice, that numberOfLives and Balance were not converted, and barkVolume was completely new data. If you have 2 Classes, that match perfectly, then hurray, but it rarely happens.
conversion can now be called from where ever you need:
Code:
Cat c = new Cat(Color.black, 9, 20, 40);
Dog d = c.toDog(50);
网友评论