1

I understand that upcasting/downcasting in objects do not change the object, but rather change how we deal with them. ( or change the type of their reference if I understand correctly).

However, if we have an Animal class that has a getName(); method, and a dog class which is a child class of Animal.

Animal Billy = new Animal("billy",1);
Dog b = (Dog)Billy;
b.getName();

I understand that it will compile, but give a run time error, my question is why, getName(); method is present in the Animal Class, and so it is inherited by the Dog class, so it's present in both, what prevents us from having it done?

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
Lifter
  • 77
  • 7
  • The first problem is that `Animal` is apparently not an abstract class. There goes your entire hierarchy. You should follow a tutorial on OOP first, they have this exact situation everywhere. – Jeroen Vannevel Aug 03 '14 at 12:19
  • 3
    Because `(Dog)` verifies that the object is, in fact a `Dog`. The cast generates (I think it's called) a CastClassCheck bytecode, and that bytecode throws a cast check exception if the referenced object is not a `Dog` or some subclass of a `Dog`. – Hot Licks Aug 03 '14 at 12:20
  • 1
    @JeroenVannevel - Why does Animal have to be an abstract class?? – Hot Licks Aug 03 '14 at 12:23
  • @HotLicks: because it is a non-sensical class. There is no such thing as an 'animal', it's just a common term for all kinds of subclasses that lead to a specific animal. Making an instance of 'animal' makes no sense. – Jeroen Vannevel Aug 03 '14 at 12:26
  • 2
    @JeroenVannevel - There most certainly is such a thing as an Animal. Or would you insist that Dog be broken down into Affenpinscher, IrishWolfhound, SiberianHusky, EnglishSetter, and 600 other breeds? – Hot Licks Aug 03 '14 at 12:30
  • @HotLicks: yes, *if* that's where it ends: subclasses of dog. That would be the same if an animal was also the end node of the tree here. But it isn't: there is a subclass of type `Dog`. You can't instantiate a common denominator when there is a more specific one inside the tree, that causes ambiguity. – Jeroen Vannevel Aug 03 '14 at 12:33
  • 1
    @JeroenVannevel - You have a very narrow understanding of OOP. Quit reading from the book and get some actual experience. – Hot Licks Aug 03 '14 at 12:36
  • @HotLicks: in order to avoid going too far here in the comments, I've created [a question over on Programmers.se](http://programmers.stackexchange.com/questions/252142/should-an-animal-be-abstract-or-allow-for-instantiation-to-represent-a-general). I'd appreciate your input. – Jeroen Vannevel Aug 03 '14 at 13:55
  • 1
    @HotLicks Nothing to do with this question, but *if* I'd already specified a class such as `Dog` I would very much *consider* making `Animal` an abstract class. It's certainly not a requirement though, as Jeroen suggests. – Maarten Bodewes Aug 03 '14 at 13:56

1 Answers1

4

Whenever you downcast check it first using instanceof operator.

Animal billy = new Animal("billy",1);

if (billy instanceof Dog) {
    Dog b = (Dog) billy;
    b.getName();
}

since Animal can be any thing Cat, Dog etc. It's not known at compile time hence before downcast you have to check it.


getName() method is present in the Animal Class, and so it is inherited by the Dog class, so it's present in both, what prevents us from having it done?

Nothing prevent you but you have to do as shown below.

If getName() method is present in Animal class then there is no need to downcast just call it on the reference of Animal class and the actual getName() method of Dog class will be called.

Animal billy = new Dog("billy",1);
billy.getName();

Read more about Overriding and Hiding Methods

enter image description here

Braj
  • 46,415
  • 5
  • 60
  • 76
  • 2
    +1 Amazing illustration :) – flotothemoon Aug 03 '14 at 12:48
  • Of course, the `instanceof` check is unnecessary if you *know* that the Animal reference is *actually* referencing a Dog. The cast operation provides a sort of "assertion check" in the event of a bug that has caused that to not be the case. You only need the `instanceof` check in the event that you're not sure. – Hot Licks Aug 03 '14 at 13:32
  • Brilliant. I do understand the material, overloading, overiding,etc, but I was interested in that case, because I've to do code tracing, and was playing around with things. Thanks a lot for you, and everyone for the great help. – Lifter Aug 03 '14 at 14:31
  • "Whenever you downcast check it first using instanceof operator" That is very poor advice. If followed as a rule, it will hide many errors. – Boann Aug 03 '14 at 15:40
  • @Boann Read more what I have suggested. So you want to say in next version of Java, `isntanceof` operator should be removed. Why `instanceof` operator is made for. Please I want to know. – Braj Aug 03 '14 at 15:40
  • @Boann how downcasting will work in Java. – Braj Aug 03 '14 at 15:43
  • I read the rest of your answer but it doesn't change the fact that the first part of it is giving very poor advice. If you require the Animal to be a Dog, it is correct to throw the ClassCastException. If we follow the advice in your question, the code will *silently do the wrong thing*. "So you want to say in next version of Java, isntanceof operator should be removed." I never said that. I said that it is wrong to use it "whenever you downcast". – Boann Aug 03 '14 at 15:47
  • @Boann please post your answer to make it for clear for other as well as me. Finally it's your opinion. Suggest which is best and correct advice. – Braj Aug 03 '14 at 15:49
  • @user3218114 The correct answer was already given by Hot Licks in the comments: "Because (Dog) verifies that the object is, in fact a Dog". I really don't understand why you can't see the problem with your answer. Do you really want code to go around *silently ignoring errors*? Yuck. – Boann Aug 03 '14 at 15:53