简体   繁体   English

如何在运行时识别对象的类型?

[英]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: 在运行时,如何在不执行以下操作的情况下,知道variants []中的给定对象是否为LandPackageVariantFlightPackageVariant类型:

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. 例如, FlightHolidayPackageVariant的字段originCity不在其他HolidayPackageVariant类中,而您想在UI中呈现它。 The object-oriented way to solve this is to make the HolidayPackageVariant responsible, in some way, for controlling its own rendering. 解决此问题的面向对象方法是使HolidayPackageVariant以某种方式负责控制其自己的呈现。 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. 现在,您的UI代码可以简单地向每个变体对象询问其详细信息,而不必知道它是哪种变体。

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. 请注意,如果您还具有从其中一种类型派生的类型,则应首先检查那些类型,因为在这种情况下,高位检查也将返回true。

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. 很好地执行此obj必须是BaseHolidayPackageVariant因此您甚至不需要BaseHolidayPackageVariant转换也不必执行if

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. 如果您希望具有特定类别Land或Flight的对象调用特定方法,则可能应检查Object模型。

You can use instanceof. 您可以使用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 看看: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. 更好的选择是设计程序,以便您不需要instanceof运算符。

You can use the instanceof operator for this: 您可以为此使用instanceof运算符:

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. 没有充分的理由使用instanceof来区分类,但是通常,子类本身应通过其公共超类的接口提供所需的不同功能。

Yeah, both answers here are - paradoxically - right. 是的,这两个答案都是-矛盾的是-对。

Tom's answer that your question is dubious is on the ball. 汤姆(Tom)的回答是您的问题值得怀疑。 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. Botz3000的答案在技术上是正确的(就像在我键入时出现的所有其他答案一样)。

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?) 在这种情况下,请使用@Override批注,在子类中重新定义方法,并在父类中提供抽象方法(或具有基础功能的具体版本?)。

From your class names, I suspect you should have a quick squiz at the Abstract Factory pattern and the (extremely simple) strategy pattern. 从您的类名来看,我怀疑您应该快速了解Abstract Factory模式和(极其简单的)策略模式。

PS If you want to get fancy and use reflection, you can just call getClass() and check that. PS:如果您想花哨并使用反射,可以只调用getClass()并进行检查。 But there is, and I want to underscore this, no reason to do this, and it is bad practice. 但是有,我想强调这一点,没有理由这样做,这是一种不好的做法。 But there you are. 但是你在那里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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