Самый простой способ - использовать встроенный в Java оператор instanceof.Например:
public boolean isAAA(Thing myThing)
{
return myThing instanceof AAA;
}
Многие люди, однако, скажут вам, что использование instanceof является симптомом плохого проектирования классов, и что правильный способ достижения различного поведения с различными подклассами - через полиморфизм.Проблема здесь в том, что в Java очень просто заставить класс сделать что-то другое в зависимости от того, какой это производный тип, но немного сложно заставить какой-то другой объект обрабатывать Thing по-разному в зависимости от того, какой производный тип имеет дескрипторна.Это проблема Double Dispatch .
Было бы идеально, если бы при обработке вашего объекта Thing вы могли просто передать проблему другим методам, которые могли бы по-разному работать в зависимости от Thing.в каком подклассе это происходит, например:
public void handleThing(Thing myThing)
{
reactToThing(myThing);
}
public void reactToThing(AAA myThing)
{
// Do stuff specific for AAA
}
public void reactToThing(BBB myThing)
{
// Do stuff specific for BBB
}
public void reactToThing(Thing myThing)
{
// Do stuff for generic Thing
}
Однако в Java, которая поддерживает только одну диспетчеризацию, независимо от фактического типа myThing в handleThing (), всегда будет вызываться responseToThing (Thing),и вы никогда не получите свое уникальное поведение.
Что вам нужно сделать, чтобы обойти эту проблему, так это использовать Шаблон посетителя .Это просто включает в себя добавление некоторого дополнительного кода в ваш класс Thing и всех его потомков, чтобы дать вашим методам reactToThing () некоторый дополнительный контекст.Итак, допустим, что все вышеперечисленные методы находятся в классе с именем Visitor.Мы можем переписать вышесказанное для работы, сначала передав проблему самому объекту Thing, а затем полиморфизм даст нам соответствующий контекст (Thing, AAA или BBB) для объекта, который нужно вернуть посетителю.
Итак, мы можем переписать приведенный выше пример следующим образом:
public class Visitor
{
// ...
public void handleThing(Thing myThing)
{
myThing.accept(this);
}
public void reactToThing(AAA myThing)
{
// Do stuff specific for AAA
}
public void reactToThing(BBB myThing)
{
// Do stuff specific for BBB
}
public void reactToThing(Thing myThing)
{
// Do stuff for generic Thing
}
}
public class Thing
{
// ...
public void accept(Visitor visitor)
{
visitor.reactToThing(this);
}
}
public class AAA
{
// ...
public void accept(Visitor visitor)
{
visitor.reactToThing(this);
}
}
public class BBB
{
// ...
public void accept(Visitor visitor)
{
visitor.reactToThing(this);
}
}
Так почему мне нужно переписать один и тот же метод accept () в обоих подклассах?Потому что в противном случае объект все равно находился бы в контексте Thing при вызове метода visitor.reactToThing (this), и, таким образом, у нас та же проблема, что и раньше.Реализовав его во всех трех местах, производный класс переопределяет реализацию родителя, и в Visitor вызывается правильный метод.
Похоже, много работы, когда все, что вы хотите знать, это какой у вас производный классработать с, но выигрыш в расширяемости и обслуживании.Теперь вам не нужно прибегать к добавлению if (что-то вроде instanceElse) повсеместно.В частности, у вас будет меньше дублирующегося кода, который необходимо поддерживать, если вы когда-нибудь решите, что вам нужно что-то изменить в будущем, например, расширить Visitor.
Надеюсь, что это ответ на ваш вопрос.