I have the following code:
class A {
}
class B extends A {
public void fB(){};
}
According to Java rule:
Case 1:
Why case 1 is OK and case 2 is not OK: Because a Dog
is an Animal
, but not every Animal
is a Dog
.
class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }
Dog fifi = new Dog();
Cat tommy = new Cat();
// OK because Dogs and Cats are Animals
Animal pet1 = fifi;
Animal pet2 = tommy;
// Not OK because an Animal is not always a Dog
Dog doggy = pet2;
Note that casting does nothing to the object; in particular, it doesn't do any kind conversion of objects. Casting is only telling the compiler "I have this object here, and I know better than you what it is; I want you to treat it as type X and not give me any error messages".
So in a line like this:
Dog doggy = pet2;
the compiler will complain because it cannot be sure that pet2
is actually a Dog
; it only knows that it is an Animal
- and not all Animal
s are Dog
s. You can do a cast to tell the compiler to not complain about this:
// Tell the compiler that you want it to treat pet2 as a Dog
Dog doggy = (Dog)pet2;
But when you run the program, Java will still check if pet2
is really a Dog
, and if it isn't, you get a ClassCastException
.
(And the question in your title is exactly the opposite of what you mean, as biziclop noticed).
Ok, think about 2 people: Doctor and Engineer. Doctor can treat, engineer can build. Both are persons.
Now here is your example.
Person p = new Person(); // somebody that does not know to do anything special.
Doctor d = (Doctor)p; // do you think that casting makes person that does not know anything to be a doctor?
Do you want to be treated by person that was "cast" to be a doctor you do you prefer the real Doctor?
I believe that the answer is clear. Each doctor is a person (case 1) but not each person is a doctor because not each person can treat. Exactly the same is relevant for class hierarchy too. Subclass inherits its super class' properties and probably adds its own. Therefore not any instance of superclass can be cast to subclass.
Case 1 is ok because with the (B)a part you are explicitly telling the compiler:
even if you only know that a is of type A I am telling you that it is of type B
so the object a is treated as if it were of type B
Case 2 is not ok because the compiler can't safely assign to b to a. It would be accepted if you wrote
A a = new A();
B b = (B)a;
but it would throw an Exception at runtime
Suppose case 2 is also working, then your compiler sees "b" as a object of class "B". Now you can say "b.fb()". But actually "b" is an object of "A"(Remember you assigned an object of class "A" to "b"). there is no function fb() in class "A". your application crashes!!