Reputation: 1338
I've read this article http://www.javapractices.com/topic/TopicAction.do?Id=31, which says using instanceof to check what my object is beforehand is a bad practice.
But I don't know how to do it otherwise in this case: I have an API that returns a List of Items. This list of Items returns both Users and Admins
If I cast an item like (User)item, I'll have a ClassCastException as soon as it hits an Admin
for(Item item : items){
if (item instanceof User){
((User)item).getName());
((User)item).getEmail());
}
else if (item instanceof Admin){
((Admin)item).getName());
((Admin)item).getEmailList().getPrimary());
}
}
Since it is an API I can't modify Item, Item do not have the methods on the childs, and the email retrieve method is different. Do I have another choice?
Upvotes: 1
Views: 1164
Reputation: 15953
Define an interface with all common methods, let User and Admin classes implementat that and use only that interface for accessing your objects in these cases.
EDIT (because you cannot change the API)
The alternative options are:
Stick to your current solution. This seems to be the best trade.
Define an interface, create two wrapper classes which implement this interface and wrap the original objects. From an OOP perspective this is more clean, but I think this is a little bit oversized in your case, but it really depends.
Theoretical(!): you could also use reflection, but don't do this - it would make the code even more worse - especially not when there are only two different compile-time known Item subtypes
Upvotes: 5
Reputation: 9048
Ideally you would change the interface to Item so that it exposed methods such that it didn't matter if you were dealing with a User or an Admin in your code -- so that Item defines both getName() and getEmail() and User and Admin implement these methods as appropriate.
However, since you don't control the API you are using then you have little choice but to write your code as you have it now.
So, the point made by the referenced article is a good one, but it assumes that you can change the classes you are working with.
Upvotes: 2
Reputation: 115328
First, your code does not have any effect. You are calling getters without any assignment, so you actually do not use the getter's return value.
Second, it is a bad practice to have collection with elements of different types. In your ccase User and Admin.
Third, if you even need such collection you can use other patterns to perform what you need. For example Visitor pattern looks like a good alternative to casting.
Upvotes: -1