简体   繁体   中英

how can I identify the type of object at runtime?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM