Проблема стирания типа Java - PullRequest
2 голосов
/ 10 июля 2009

Я сделал пример, чтобы продемонстрировать свою проблему:

Metrical.java

public interface Metrical<T>
{
    double distance(T other);
}

Widget.java

public class Widget implements Metrical<Widget>
{
    private final double value;

    public Widget(double value) { this.value = value; }

    public double getValue() { return value; }

    public double distance(Widget other) { return Math.abs(getValue() - other.getValue()); }
}

Pair.java

public class Pair<T>
{
    private final double value;
    private final T object1, object2;

    public Pair(T object1, T object2, double value)
    {
        this.object1 = object1;
        this.object2 = object2;
        this.value = value;
    }

    public T getObject1() { return object1; }

    public T getObject2() { return object2; }

    public double getValue() { return value; }
}

Algorithm.java

import java.util.Set;

public class Algorithm<T extends Metrical<T>>
{
    public void compute(Set<T> objects)
    {

    }

    public void compute(Set<Pair<T>> pairs)
    {

    }
}

Итак, в Algorithm.java , Set > рассматривается как Set , и поэтому у меня есть тип проблемы стирания. Тем не менее, есть ли способ, которым я могу избежать такого, не называя методы по-другому? Оба варианта алгоритма предназначены для работы с T , но мне нужно учесть разные аргументы. Они вычисляют одно и то же, поэтому, чтобы избежать путаницы, я бы не стал называть их по-другому. Есть ли способ приспособиться к этому?

Ответы [ 5 ]

4 голосов
/ 10 июля 2009

Нет, нет.

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

Вот почему ты не можешь этого сделать. Так же, как вы не можете сделать:

interface A {
  void blah(Set set);
  void blah(Set<T> set);
}

Та же проблема.

Информация о типе недоступна во время выполнения (т. Е. Стирание типа).

3 голосов
/ 10 июля 2009

К сожалению, это основная область, где Java Generics рушится ... просто не существует хорошего решения.

Я обычно прибегал к созданию нового класса с интерфейсом Set<Pair<T>>, но это обернуло Set<Pair<T>> (без его расширения, что вызвало бы ту же проблему).

3 голосов
/ 10 июля 2009

Извините, плохая новость в том, что вы не можете сделать это:

public class Algorithm<T extends Metrical<T>> {
    public void compute(Set<T> objects) {
    }

    public void compute(Set<Pair<T>> pairs) {
    }
}

Из-за удаления оба файла будут стерты с одинаковой подписью. Нет никакого способа обойти одно из перечисленных методов.

0 голосов
/ 30 ноября 2011

Использование public class Widget<K, P> implements Metrical<K extends Widget<P>>.

public double distance(Widget other) {} становится public double distance(Widget<P> other) {}

0 голосов
/ 03 января 2011

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

См. Также: Использование TypeTokens для получения общих параметров

Надеюсь, это поможет.

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