определение подкласса во время выполнения - PullRequest
1 голос
/ 02 ноября 2009

Я хочу знать, как определить подклассы во время выполнения в Java. В моей программе я вызываю метод, который возвращает объект суперкласса. Объект может быть экземпляром любого из его подклассов. Я хочу знать, что объект является экземпляром какого подкласса во время выполнения, чтобы я мог привести его к этому подклассу и получить доступ к методам подкласса. Может ли кто-нибудь помочь мне в этом?

Спасибо

Ответы [ 6 ]

7 голосов
/ 02 ноября 2009

Вы можете просто использовать instanceof, чтобы проверить, является ли объект экземпляром определенного класса. например:

if (animal instanceof Cat) {
    Cat cat = (Cat) animal;
    cat.meow();
} else if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();
}

Однако чрезмерное использование instanceof (или, в данном случае, понижение) обычно считается признаком плохого дизайна. Лучше вместо этого использовать полиморфизм. Например, имейте (возможно, абстрактный) метод «говорить» в Animal, и тогда у каждого подкласса будет своя реализация. Приведенный выше код будет заменен на призыв говорить:

animal.speak();
4 голосов
/ 02 ноября 2009

Вызовите getClass () для объекта, чтобы получить доступ к объекту Class, который сообщает вам фактический тип объекта. Затем вы можете сравнить это со статическим членом ".class" любого класса.

if (obj.getClass().equals(Foo.class)) { ... }

Однако многие скажут, что вы предлагаете плохой дизайн. Убедитесь, что это необходимо, и рассмотрите альтернативы. Это часто необходимо при реализации методов, подобных equals ().

1 голос
/ 02 ноября 2009

Вы можете использовать оператор instanceof и прямое сравнение объектов Class, как было упомянуто выше.

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

  • Шаблон посетителя GoF ;
  • инкапсулирует специфичную для класса логику обработки, т.е. создайте что-то вроде этого:

interface Handler<T> {
    void handle(T object);
}

Map<Class<?>, Handler<?>> HANDLERS = /* init handlers mappings */;

...

public void process(Object obj) {
    Handler<?> handler = HANDLERS.get(obj.getClass());
    if (handler == null) {
        throw new IllegalStateException("bla-bla-bla, no handler is registered for class " + obj.getClass());
    }
    handler.handle(obj);
}
1 голос
/ 02 ноября 2009

Обратите внимание, instanceof имеет значение true, если объект является типом, присваиваемым класс указан. Следующее (как описано выше) будет работать

if (o instanceof Cat.class) {
  // ..
} else if (o instanceof Dog.class) {
  // ..
} else {
  throw IllegalArgumentException("Unexpected type");
}

Однако, если вы введете новый подкласс cat, например, Тигр тогда первый пункт выше будет срабатывать, если вы не обновили весь код что сделал это

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

1 голос
/ 02 ноября 2009

Используйте оператор instanceof. Как это

Superclass aSup = ...;
if(aSup instanceof Subclass) {
    Subclass aSub = (Subclass) aSup;
    aSub.subclass_method(...);
}
0 голосов
/ 02 ноября 2009

Вы можете использовать оператор instanceof для проверки типа объекта, а затем приведения.

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