Автоматическое преобразование типов в Java? - PullRequest
4 голосов
/ 09 марта 2010

Есть ли способ сделать автоматическое неявное преобразование типов в Java? Например, скажем, у меня есть два типа, «FooSet» и «BarSet», которые оба являются представлениями набора. Преобразование между типами легко, так что я написал два служебных метода:

/** Given a BarSet, returns a FooSet */
public FooSet barTOfoo(BarSet input) { /* ... */ }

/** Given a FooSet, returns a BarSet */
public BarSet fooTObar(FooSet input) { /* ... */ }

Теперь скажите, что есть такой метод, который я хочу вызвать:

public void doSomething(FooSet data) {
    /* .. */
}

Но все, что у меня есть, это BarSet myBarSet ... это означает дополнительный набор текста, например:

doSomething(barTOfoo(myBarSet));

Есть ли способ сообщить компилятору, что определенные типы могут автоматически приводиться к другим типам? Я знаю, что это возможно в C ++ с перегрузкой, но я не могу найти способ в Java. Я просто хочу набрать:

doSomething(myBarSet);

И компилятор знает, как автоматически вызвать barTOfoo()

Ответы [ 6 ]

5 голосов
/ 09 марта 2010

Ответ короткий: это возможно с перегрузкой в ​​C ++, но в Java нет способа сделать это.

2 голосов
/ 09 марта 2010

Вы можете перегрузить ваши методы, примерно так:

public void doSomething(FooSet data) {
    /* .. */
}

public void doSomething(BarSet data) {
    doSomething(barTOfoo(data));
}
1 голос
/ 09 марта 2010

Вы можете сделать оба вместе:

(1) Напишите методы-оболочки, которые выполняют преобразование в фоновые сцены.

(2) Если ваши объекты имеют правильный переопределенный метод hashCode, методы-обертки могут управлять очень простым и быстрым кешем, который вы можете создать самостоятельно с помощью простой реализации Map и, возможно, синхронизации (если вы используете объекты одновременно на всех).

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

Удачи.

0 голосов
/ 09 августа 2012

Автоматическое преобразование типов не поддерживается (для этого вам нужно неявное преобразование типов Scala ).

Но вы можете попробовать использовать тип Variant в качестве распределительной коробки для переключения между типами:

/** Given a BarSet, returns a FooSet */
public Function<BarSet, FooSet> barTofoo = new Function<BarSet, FooSet>() {
    @Override public FooSet apply(BarSet input) { /* ... */ }
}

/** Given a FooSet, returns a BarSet */
public Function<FooSet, BarSet> fooToBar = new Function<FooSet, BarSet>() {
    @Override public BarSet apply(FooSet input) { /* ... */ }
}

/** Create a type conversion context in which both of these conversions are registered */
TypeConversionContext fooBarConversionContext = MatchingTypeConversionContext.builder()
    .register(FooSet.class, BarSet.class, fooToBar)
    .register(BarSet.class, FooSet.class, barToFoo)
    .build();

/** Put a FooSet into a Variant, bound to our type conversion context */
FooSet fooSet = new FooSet();
Variant data = Variant.of(fooSet).in(fooBarConversionContext);

/** Pull a BarSet out of the Variant */
public void doSomething(Variant data) {
    Preconditions.checkArgument(data.isConvertibleTo(BarSet.class);
    BarSet barSet = data.as(BarSet.class);
    // ...
}
0 голосов
/ 09 марта 2010

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

0 голосов
/ 09 марта 2010

Перегрузка работает противоположным образом, вы объявляете два метода для объекта-получателя:

public void doSomething(FooSet data)
{
    /* .. */
}

public void doSomething(BarSet data)
{
    doSomething(barToFoo(data));
}

тогда благодаря Dynamic Binding ( wikipedia ) правильный метод выбран во время выполнения.

Конечно, перегрузка в Java ограничена на уровне объектов (поскольку вызовы ограничены экземплярами или объявлениями классов), но работает аналогичным образом.

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

...