簡體   English   中英

如何在運行時識別對象的類型?

[英]how can I identify the type of object at runtime?

類:

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;
}

在運行時,如何在不執行以下操作的情況下,知道variants []中的給定對象是否為LandPackageVariantFlightPackageVariant類型:

if(holidayPackageType.equals("LandHolidayPackageVariant")
 obj = (LandHolidayPackageVariant)variant[i];
else if(holidayPackageType.equals("FlightHolidayPackageVariant")
 obj = (FlightHolidayPackageVariant)variant[i];

這個問題源於我在這里提出的設計問題

在一個好的面向對象設計中,您永遠不需要知道對象是否屬於特定類型。 您只需在其上調用方法,對象就可以完成正確的操作。

例如, FlightHolidayPackageVariant的字段originCity不在其他HolidayPackageVariant類中,而您想在UI中呈現它。 解決此問題的面向對象方法是使HolidayPackageVariant以某種方式負責控制其自己的呈現。 假設您的用戶界面將顯示每個變體的屬性列表。 您可以讓變體提供這些列表:

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;
    }
}

現在,您的UI代碼可以簡單地向每個變體對象詢問其詳細信息,而不必知道它是哪種變體。

嘗試這個:

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
}

請注意,如果您還具有從其中一種類型派生的類型,則應首先檢查那些類型,因為在這種情況下,高位檢查也將返回true。

更好的方法可能是讓派生的類通過定義要在基類上重寫的適當方法來實現所需的特定邏輯。 這樣,您無需檢查類型,就可以充分利用多態性。

像這樣:

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];

很好地執行此obj必須是BaseHolidayPackageVariant因此您甚至不需要BaseHolidayPackageVariant轉換也不必執行if

如果您希望具有特定類別Land或Flight的對象調用特定方法,則可能應檢查Object模型。

您可以使用instanceof。

例如: {

enter code here
if (variant[i] instanceof LandHolidayPackageVariant) {
  //do something
} else if(variant[i] instanceof FlightHolidayPackageVariant){
  //do something
}

}

看看:http://www.java2s.com/Tutorial/Java/0060__Operators/TheinstanceofKeyword.htm

更好的選擇是設計程序,以便您不需要instanceof運算符。

您可以為此使用instanceof運算符:

if (variant[i] instanceof LandHolidayPackageVariant)
    obj = (LandHolidayPackageVariant) variant[i];

但是,通常您不需要它。 沒有充分的理由使用instanceof來區分類,但是通常,子類本身應通過其公共超類的接口提供所需的不同功能。

是的,這兩個答案都是-矛盾的是-對。

湯姆(Tom)的回答是您的問題值得懷疑。 通常沒有理由從對象的層次結構中確定其他對象的特定類型。 (我的意思是在花哨的反射用途之外)

Botz3000的答案在技術上是正確的(就像在我鍵入時出現的所有其他答案一樣)。

猜測,您正在計算要在類中調用的方法? 在這種情況下,請使用@Override批注,在子類中重新定義方法,並在父類中提供抽象方法(或具有基礎功能的具體版本?)。

從您的類名來看,我懷疑您應該快速了解Abstract Factory模式和(極其簡單的)策略模式。

PS:如果您想花哨並使用反射,可以只調用getClass()並進行檢查。 但是有,我想強調這一點,沒有理由這樣做,這是一種不好的做法。 但是你在那里。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM