Как я могу определить тип объекта во время выполнения? - PullRequest
0 голосов
/ 22 марта 2012

классы:

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

Во время выполнения, как я могу узнать, имеет ли данный Объект в вариантах [] тип LandPackageVariant или FlightPackageVariant без выполнения каких-либо действий:

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

Этот вопрос вытекает из вопроса о дизайне, который я задал здесь

Ответы [ 7 ]

5 голосов
/ 22 марта 2012

В хорошем объектно-ориентированном дизайне вам не нужно знать, принадлежит ли объект определенному типу.Вы просто вызываете методы для него, и объект делает правильные вещи.

Например, FlightHolidayPackageVariant имеет поле originCity, которого нет в других HolidayPackageVariant классах, и вы хотите визуализироватьчто в интерфейсе.Объектно-ориентированный способ решения этой проблемы состоит в том, чтобы заставить 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;
    }
}

Теперь ваш код пользовательского интерфейса может просто запросить каждый вариантный объект для его деталей, без необходимости знать, какой это вариант.

3 голосов
/ 22 марта 2012

попробуйте это:

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
}

Обратите внимание, что если у вас также есть типы, производные от одного из этих типов, вы должны проверить эти first , так как верхние проверки вернут true дляв этом случае тоже.

Лучшим подходом может быть позволить производным классам реализовать требуемую специфическую логику посредством определения соответствующих методов, которые должны быть переопределены в базовом классе.Таким образом, вам не нужно проверять типы и использовать все преимущества полиморфизма.

1 голос
/ 22 марта 2012
if(holidayPackageType.equals("LandHolidayPackageVariant")
 obj = (LandHolidayPackageVariant)variant[i];
else if(holidayPackageType.equals("FlightHolidayPackageVariant")
 obj = (FlightHolidayPackageVariant)variant[i];

Хорошо делать это obj должно быть BaseHolidayPackageVariant, так что вам даже не нужно ни разыгрывать, ни делать if вещь.

Если вы хотите, чтобы объект с определенным классом Land или Flight вызывал определенный метод, то, возможно, вам следует пересмотреть модель объекта.

1 голос
/ 22 марта 2012

как это:

if(object instanceof LandPackageVariant) {
    System.out.println("it's a LandPackageVariant");
}
0 голосов
/ 22 марта 2012

Да, оба ответа здесь - как это ни парадоксально - правильно.

Ответ Тома о том, что ваш вопрос сомнителен, находится на высоте. Как правило, нет причин определять конкретный тип объекта из других в его иерархии. (Я имею в виду за пределами фантазии использования-отражения)

Ответ Botz3000 (как и все остальные, которые только появились при вводе текста) технически верен.

Как вы думаете, вы решаете, какой метод вызывать в классе? В этом случае используйте аннотацию @Override, переопределите метод в дочерних классах и предоставьте абстрактный метод в родительском (или конкретную версию, которая делает базовые вещи?)

Из ваших имен классов, я подозреваю, вы должны быстро провести тест на шаблон Абстрактной фабрики и (чрезвычайно простой) шаблон стратегии.

PS Если вы хотите получить fancy и использовать отражение, вы можете просто вызвать getClass () и проверить это. Но есть, и я хочу подчеркнуть это, нет причин делать это, и это плохая практика. Но вот ты где.

0 голосов
/ 22 марта 2012

Для этого вы можете использовать оператор instanceof:

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

Однако обычно вам это не нужно. Существует несколько веских причин для использования instanceof для различения классов, но обычно сами подклассы должны обеспечивать различную функциональность, необходимую через интерфейс их общего суперкласса.

0 голосов
/ 22 марта 2012

Вы можете использовать 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

Лучшим вариантом было бы разработать свою программу так, чтобы вам не нужен экземпляр Operator.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...