-1

I am looking for some advice on how I could approach the following scenario:

Let's say I have an array of a type and in that array there are objects of various types that extend said type. For example: I have a super class Pet, I make a Pet array, and then put various objects of Dog, Cat, and Fish classes and put them in this array. Now, each type of pet has its own fields and methods, naturally.

This is where my issue comes into play. I want to loop through this array and search for a specific object and call one of its methods. Building off my previous example, I want to search for a Dog by the name of "Benny". Once I find it, I want to call Benny's getHairLengthmethod. However, if I'm iterating through my collection of various Pet types, I cannot call Pet[index].getHairLength since not all pets have this method(only Dogs do).

Any tips?

Syed Farjad Zia Zaidi
  • 3,302
  • 4
  • 27
  • 50
  • You can [down cast](http://stackoverflow.com/q/380813/572670) your `Pet` into a `Dog`. However, note that needing to do so is a definite [code smell](http://en.wikipedia.org/wiki/Code_smell). – amit May 29 '14 at 23:18
  • Casting? `((Dog)Pet[index]).getHairLength`? – Bernhard Barker May 29 '14 at 23:18
  • @Dukeling Please don't encourage unsafe casting without giving the warning about it... – amit May 29 '14 at 23:20
  • I've tried casting, but I get a ClassCastException in my case... – user3689439 May 29 '14 at 23:21
  • @user3689439 You need to first make sure this object is a `Dog`, and this solution scales terribly, you should just hold a different list of `Dog` objects, or provide a common interface that you can use. – amit May 29 '14 at 23:22
  • @amit Alright, I will try to go by it that way. I was just wondering, though, could I use the instanceof operator at all in this case? – user3689439 May 29 '14 at 23:25
  • Yes, but again - it will be a bad practice. You can use: `for(Pet p : pets) if (p instanceof Dog) { Dog d = (Dog)p; .... }`, but I really discourage this coding style. – amit May 29 '14 at 23:28

2 Answers2

0
if(pet[index] instanceof Dog) {
    ((Dog)pet[index]).getHairLength();
}
0

1) You can definitely cast "Pet" (superclass) to "Dog" (subclass). Whether you should is another question, but you "can".

2) If you're getting a ClassCastException ... then you've done something wrong. You're saving the wrong object or the wrong type. We'd need to see the code to troubleshoot.

3) One solution is to save "Pets" to a list, then have an if/else block:

  Pet p = pets[i];
  if (p instanceof Dog)
     ...
  else if (p instanceof Cat)
     ...

4) Another solution is to save the same object to as many distinct lists as makes sense:

  List<Pet> pets = new ArrayList<Pet>();
  List<Dog> dogs = new ArrayList<Dog>();
  ...
  Dog fido = new Dog (...);
  pets.add(fido);
  dogs.add(fido);

This way, you can:

a) Search for "dogs" more efficiently (you won't have to deal with any "cats" or "goldfish")

b) You don't have to cast anything

c) You still maintain complete flexibility to aggregate your "pets".

FoggyDay
  • 11,962
  • 4
  • 34
  • 48