• Post Reply Bookmark Topic Watch Topic
  • New Topic

Looking for pattern to avoid instanceof  RSS feed

 
Kenny Vermeers
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

So I'm looking for a pattern to avoid the following use of instanceof (see code below). One solution would be to have a method getDetails() implemented in all animals. The problem then is that they have different return values for different sublcasses. So the issue really comes down to this. How to avoid instanceof as a check to know whether the object has a certain method implemented before it is called. One way this can be avoided is to have methods "hasTrunk" in Animal set to false, and then override it to true in Elephant. Then call if (animal.hasTrunk()) animal.getTrunkLength() but this seems kind of annoying since this would add a method hasXXXX() to animal for every specific detail. Thanks for your help.

 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

Do all animals have necks? Do all necks have a length? In which case can you put the neck length method in the Animal class?
Do all animals have noses? Do all noses have a length?
Can you create a common getDetails method in the Animal class? Can you create a Details class which will encapsulate the details of a particular animal? Any getDetails method should be in the animal class not in another class.

If you can't sort it out like that, then I think there isn't a pattern which will allow you to do what you want with simple inheritance. Once you start adding fields and methods, your inheritance ceases to work normally.
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You cannot have methods with variable return type but (since Java5) you can have methods with covariant return type; the return type of a(n overriding) subclass method is a subtype of the return type of the superclass method.
 
Stephan van Hulst
Saloon Keeper
Posts: 7974
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would argue that if you don't know what to return, the caller of your method probably doesn't have much use for it anyway.

What would the use for a method getDetails() be? What do you expect clients to do with that information? If they just need to print it, return a String.
 
Kenny Vermeers
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, thanks for the quick reply!

No, not all animals have necks and not all animals have trunks. Its an attribute specific to the subclasses Giraf and Elephant. But there could e.g. be a subclass "Elegiraf" which has both trunklength and necklength. The common getdetails method wouldn't work because it would return different objects (in this case int and float but could be any kind of different objects).
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A details class can encapsulate a String for the name of the feature and a number for its value. Or you can have a Map<String, Integer> for several features.

OP: Don't use floats. If you need floting‑point arithmetic use a double.
 
Tushar Goel
Ranch Hand
Posts: 934
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
you can have methods with covariant return type; the return type of a(n overriding) subclass method is a subtype of the return type of the superclass method.

I forgot this type of overriding. Thanks for reminding.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Kenny Vermeers wrote:No, not all animals have necks and not all animals have trunks. Its an attribute specific to the subclasses Giraf and Elephant. But there could e.g. be a subclass "Elegiraf" which has both trunklength and necklength. The common getdetails method wouldn't work because it would return different objects (in this case int and float but could be any kind of different objects).

Then I'd say you should look at Stephan's reply again and try to answer his question: What would use a getDetails() method?

If each type of animal has different characteristics and there's not much commonality between them, then I'd say that any logic that deals with "details" should be in each specific animal class, since only a Cat knows what a Cat "has".

Now, depending on what you want to DO with those details, you might be able to generalise. For example, a polymorphic printDetails() method should be quite simple; but a polymorphic structure isn't.

HIH

Winston
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In addition to what others have said, your idea to use a hasX() method would not work. An Animal reference can only call methods defined in the Animal class, it cannot call methods defined in the Elephant subclass or the Giraffe subclass. Code like the following would fail to compile:



However, even if it did compile it would not be a good replacement for using instanceof. The above code is semantically identical to instanceof. The reason instanceof is generally bad practice is because it leads to non-object-oriented code, and the code I wrote above has exactly the same flaw.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!