2013-06-14 2 views
1

Как бы выразить следующий тип отношений в Java дженериков:Общие типы переменных типа?

class MyClass<T> { } 

interface MyInterface<T extends MyClass> { 
    void m1(T<Integer> argument); 
    void m2(T<String> argument); 
    void m3(T<?> argument); 
} 

без компилятора жалобы. Возможно ли это? Я хочу удостовериться, что все методы получают тот же (дополнительный) класс MyClass, не нарушая безопасность типа. В домене разные подклассы og MyClass не будут иметь места. Действительно ли я должен перечислить три общие переменные типа, как это:

class MyClass<T> { } 

interface MyInterface<T1 extends MyClass<Integer>, 
    T2 extends MyClass<String>, T3 extends MyClass<?>> { 
    void m1(T1 argument); 
    void m2(T2 argument); 
    void m3(T3 argument); 
} 

Я чувствую, как это страшно читать и не делает ни выразить свое намерение так хорошо, как я хотел. Этот вопрос связан с моим другим вопросом о дженериках Raw types inside of generic definition, который все еще меня смущает. Может быть, кто-то может помочь! Спасибо.

+2

Вы определенно не можете использовать 'T <>' в Java-генераторах. Ваше решение, вероятно, является наилучшим доступным решением. –

+0

Ну, проблема в том, что у меня есть интерфейс с arround 20 разных типов ... Я ненавижу использование этого интерфейса, и все же мне это нужно. Либо пользователи не получают безопасности по типу, либо печатают навсегда, оба решения не совсем такие. –

ответ

0

Ну, я REA lized, что я получаю, потому что я не могу выразить это в Java:

class MyClass<T> { } 

interface MyInterface<T extends MyClass> { 
    T<S> m1(S argument); 
} 

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

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

0

Не уверен, что это хороший способ. Я чувствую, используя ниже методы вы можете не «связывать» параметры m1, m2, m3 метод, вместо того, чтобы во время разговора вы можете иметь привилегию использования любого рода параметры, будь то MyClass<Integer> или MyClass<String>

public class MyClass<T> { } 

interface MyOtherClass<T extends MyClass<?>> { 
    void m1(T argument); 
    void m2(T argument); 
    void m3(T argument); 
} 

И реализатор

class MyOtherClassImpl<T extends MyClass<?>> implements MyOtherClass<T> { 

    @Override 
    public void m1(T argument) { 

    } 

    @Override 
    public void m2(T argument) { 

    } 

    @Override 
    public void m3(T argument) { 

    } 

} 

и это, как вы можете позвонить

MyOtherClass<MyClass<?>> otc = new MyOtherClassImpl<MyClass<?>>(); 
    MyClass<Integer> m1 = new MyClass<Integer>(); 
    MyClass<String> m2 = new MyClass<String>(); 
    MyClass<Object> m3 = new MyClass<Object>(); 
    otc.m1(m1); 
    otc.m2(m2); 
    otc.m3(m3); 
+0

Проблема с этим решением заключается в том, что я теряю всю безопасность типов в 'MyInterface'. Я просто должен предположить, что ограничения заданы правильно и в противном случае будут неприятными 'ClasscastException' во время выполнения, если они будут применяться неправильно. Кроме того, это не будет работать при использовании общего параметра в качестве возвращаемого типа, когда безопасность типа имеет значение для конечного пользователя. –

Смежные вопросы