classes:
public abstract class BaseHolidayPackageVariant {
private Integer variantId;
private HolidayPackage holidayPackage;
private String holidayPackageType;
}
public class LandHolidayPackageVariant extends BaseHolidayPackageVariant{
}
public class FlightHolidayPackageVariant extends BaseHolidayPackageVariant{
private Destination originCity;
}
public class HolidayPackage{
ArrayList<BaseHolidayPackageVariant> variants;
BaseHolidayPackageVariant defaultVariant;
}
At runtime, how can I know if a given Object in variants[] is of Type LandPackageVariant
or FlightPackageVariant
without doing something of the sorts of:
if(holidayPackageType.equals("LandHolidayPackageVariant")
obj = (LandHolidayPackageVariant)variant[i];
else if(holidayPackageType.equals("FlightHolidayPackageVariant")
obj = (FlightHolidayPackageVariant)variant[i];
This question stems from a design question I asked here
In a good object-oriented design, you shouldn't ever need to know if the object is of a particular type. You just call methods on it, and the object does the right thing.
For example, FlightHolidayPackageVariant
has a field originCity
that isn't in the other HolidayPackageVariant
classes, and you want to render that in the UI. The object-oriented way to solve this is to make the HolidayPackageVariant
responsible, in some way, for controlling its own rendering. Let's say your UI is going to show a list of properties for each variant. You can let the variants supply those lists:
public abstract class BaseHolidayPackageVariant {
private int cost;
public Map<String, String> getDetails() {
HashMap<String, String> details = new HashMap<String, String>();
details.put("cost", String.format("%.2f", cost / 100.0));
return details;
}
}
public class FlightHolidayPackageVariant extends BaseHolidayPackageVariant {
private Destination originCity;
@Override
public Map<String, String> getDetails() {
Map<String, String> details = super.getDetails();
details.put("origin city", originCity.getName());
return details;
}
}
Now, your UI code can simply ask each variant object for its details, without having to know what kind of variant it is.
try this:
if (variant[i] instanceof LandHolidayPackageVariant) {
LandHolidayPackageVariant obj = (LandHolidayPackageVariant)variant[i];
// do stuff
}
else if (variant[i] instanceof FlightHolidayPackageVariant) {
FlightHolidayPackageVariant obj = (FlightHolidayPackageVariant)variant[i];
// do other stuff
}
Note that if you also have types derived from one of those types, you should check for those first , as the upper checks would return true for that case, too.
A better approach might be to let the derived classes implement the required specific logic via defining appropriate methods to be overridden on the base class. That way you don't need to check for the types and can take full advantage of polymorphism.
like this:
if(object instanceof LandPackageVariant) {
System.out.println("it's a LandPackageVariant");
}
if(holidayPackageType.equals("LandHolidayPackageVariant")
obj = (LandHolidayPackageVariant)variant[i];
else if(holidayPackageType.equals("FlightHolidayPackageVariant")
obj = (FlightHolidayPackageVariant)variant[i];
Well doing this obj
has to be a BaseHolidayPackageVariant
so you don't even need to cast nor to do the if
thingy.
If you want an object with the specific class Land or Flight to call a specific method, then maybe you should review your Object model.
You can use instanceof.
For example: {
enter code here
if (variant[i] instanceof LandHolidayPackageVariant) {
//do something
} else if(variant[i] instanceof FlightHolidayPackageVariant){
//do something
}
}
Take a look at:http://www.java2s.com/Tutorial/Java/0060__Operators/TheinstanceofKeyword.htm
A better option would be to design you program so that you don't need the instanceof Operator.
You can use the instanceof
operator for this:
if (variant[i] instanceof LandHolidayPackageVariant)
obj = (LandHolidayPackageVariant) variant[i];
However, usually you shouldn't need it. There are few good reasons to use instanceof
to differentiate between classes, but usually the subclasses themselves should provide the different functionality needed through their common super class' interface.
Yeah, both answers here are - paradoxically - right.
Tom's answer that your question is dubious is on the ball. There generally isn't a reason to determine an object's specific type from other's in its hierarchy. (I mean outside of fancy reflection-uses)
Botz3000's answer is (like all the others that just appeared as i type) technically correct.
At a guess, you're working out which method to call in the class? In which case, use the @Override annotation, re-define the method in the child classes, and provide an abstract method in the parent (or a concrete version that does base things?)
From your class names, I suspect you should have a quick squiz at the Abstract Factory pattern and the (extremely simple) strategy pattern.
PS If you want to get fancy and use reflection, you can just call getClass() and check that. But there is, and I want to underscore this, no reason to do this, and it is bad practice. But there you are.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.