Java полиморфизм и уныние - PullRequest
6 голосов
/ 13 июня 2011

Я играю с API отражения Java и пишу методы, которые проверяют данный объект и описывают его поля, методы и т. Д.

Я использую метод getFields() для итерацииразличные атрибуты и отображение содержимого объекта:

public static void display(Integer i)
{
    System.out.println("An integer: " + i);
}

// Basically a method for each primitive type wrapper

public static void display(Object o)
{
    for (Field f : c.getFields())
    {
        System.out.println("A " + o.getClass() + " which is composed of:");
        display(f.get(o));
    }
}

(Другие примитивные типы и массивы для простоты опущены.)

Eventhough Field 'get метод возвращает Object, Я думал, что правильные методы будут вызываться для оболочек примитивного типа (целые числа, строки и т. Д.), Но на самом деле вызывается только display(Object o) (неявное понижение не выполняется).

На данный момент,единственное решение, которое я нашел, - это жестоко опустить объекты, если это возможно, следующим образом:

public static void display(Object o)
{
    if (o instanceof Integer)
    {
        display((Integer) o);
        return;
    }
    else if (o instanceof String 
    {
        ... 
    } // And so on

    for (Field f : c.getFields())
    {
        System.out.println("A " + o.getClass() + " which is composed of:");
        display(f.get(o));
    }
}

Это, однако, кажется уродливым, и мне было интересно, есть ли более элегантный способ убедиться, что правильный методназывается.Есть идеи?

Заранее спасибо, хорошие люди из StackOverflow!

Ответы [ 3 ]

3 голосов
/ 13 июня 2011

Хороший вопрос. Мне тоже было интересно вчера вечером;)

Таким образом, ответ заключается в том, что существует 2 различных типа полиморфизма: полиморфизм во время компиляции и во время выполнения.

Когда вы используете метод супертипа и переопределяете методы sybtypes, это полиморфизм во время выполнения.

Когда вы используете супертипы и подтипы в качестве параметров для различных перегруженных методов, это полиморфизм во время компиляции.

Таким образом, компилятор, в вашем случае, должен знать во время компиляции, какой метод (/ overload) выполнить, он не примет это решение во время выполнения.

Если бы у вас был Контроль над классом поля, то решением было бы использовать обобщенные значения, чтобы вы определили

class Field<T> 

по методу

T get( Object o )

Тогда компилятор сможет знать, во время компиляции, какой метод использовать для отображения, как он будет знать, во время компиляции, какой тип возвращается field.get.

Но, согласно вашим комментариям, вы используете класс JDK java.lang.reflect.Field и, следовательно, не можете управлять им, чтобы сделать его универсальным. В этом случае, да, единственным решением является использование метода отображения, который обрабатывает все возможные типы для field.get. Но действительно, метод String.valueOf может сильно помочь в этом, поскольку он предоставляет строковое представление любого типа в Java, уже выполняя искомую работу по перегрузке.

Источник здесь .

С уважением, Stéphane

1 голос
/ 13 июня 2011

То, что вы хотите - это так называемая «двойная отправка», которую Java не поддерживает.

Вы можете смоделировать это с помощью отражения: проверьте все свои display методы и их типы аргументов и динамически вызовите один из них в зависимости от типа объекта во время выполнения.

Это излишне умно для этой проблемы. Ваша цепочка if-else просто в порядке.

0 голосов
/ 13 июня 2011

Java не поддерживает «множественный полиморфизм». Возможно, вы захотите взглянуть на шаблон посетителя. Это почти пример из учебника для посетителей.

...