Проблема определения общего интерфейса - PullRequest
2 голосов
/ 09 января 2009

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

Допустим, у меня есть общее Сообщение класс

public class Message<T> {

    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }

}

и затем я хочу определить интерфейс для передачи вещей:

public interface Transfer<Message<T>> {

    public void send(Message message);

}

Проблема в том, что компилятор не принимает это и всегда жалуется на второй символ «<», независимо от того, какие варианты я пробую. Как мне указать этот интерфейс, чтобы он был связан с универсальным типом (на основе сообщения) а также есть доступ к параметризованному типу? </p>

Я планировал использовать этот интерфейс следующим образом:

public class Carrier<Message<T>> implements Transfer<Message<T>> {

    public void send(Message message) {
        T content = message.getContent();
        print(content);
    }

    public static void print(String s) {
        System.out.println("The string equals '" + s + "'");
    }

    public static void print(Integer i) {
        System.out.println("The integer equals " + i);
    }

    public static void main(String[] args) {
        Carrier<Message<String>> stringCarrier = new Carrier<Message<String>>();
        Message<String> stringMessage = new Message<String>("test");
        stringCarrier.send(stringMessage);

        Carrier<Message<Integer>> integerCarrier = new Carrier<Message<Integer>>();
        Message<Integer> integerMessage = new Message<Integer>(123);
        integerCarrier.send(integerMessage);
    }
}

Я провел некоторый поиск и чтение (среди прочего generic faq от Angelika), но я не могу сказать, если это невозможно или я делаю это неправильно.

Обновление 2009-01-16 : Удалено исходное использование «Вещи» вместо «Сообщение » (которое использовалось, потому что с этим я смог скомпилировать без получения синтаксических ошибок на интерфейс).

Ответы [ 3 ]

5 голосов
/ 09 января 2009

Мне кажется, что ты хочешь:

public class Carrier<Thing extends Message<Foo>, Foo>
    implements Transfer<Thing>

Таким образом, компилятор узнает, что thing является Message<Foo>, и поэтому будет иметь метод getContent ().

Вам нужно будет использовать его как:

Carrier<Message<String>, String>

Но в настоящее время у вас есть немного разобщенности. Вы реализуете Transfer<Thing>, но вы пытаетесь использовать thing, как если бы это был Message<Thing> взгляд на ваш send метод - вы вызываете его со String и Integer. Эти классы не имеют getContent() методов.

Я подозреваю, что вы на самом деле должны реализовывать Transfer<Message<Thing>> вместо Transfer<Thing>

0 голосов
/ 16 января 2009

Вам нужно только указать T для класса, а затем использовать Message для типов аргументов / возвращаемых значений.

public interface Transfer<T> {
    public void send(Message<T> message);
}

Причина, по которой вы не используете Message , заключается в том, что вы предоставляете контекст «это сообщение» в своих аргументах и ​​возвращаемых типах.

0 голосов
/ 16 января 2009

Независимо от того, как вы решите проблему универсальности, ваш код не будет компилироваться, потому что у вас нет метода печати, который принимает тип T в качестве параметра.

Я полагаю, что вам придется выполнять проверку экземпляров, если вы хотите ту функциональность, которую вы ищете. Поэтому я не думаю, что в этом случае вы получаете какое-либо значение от универсального типа.

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