2010-03-04 4 views
3

Я пытаюсь реорганизовать класс и набор подклассов, где тип M действительно расширяет что-либо, хотя мы знаем, что он должен быть подклассом определенного типа. Этот тип параметризован, и я хотел бы, чтобы его параметризованные типы были доступны для подклассов, у которых уже есть значения для M.Extract Generic types from extended Generic

Есть ли способ определить этот класс без необходимости включать избыточные типы K и V в список параметров , Я хотел бы иметь возможность компилятора вывести их из того, что M отображается на подклассы.

public abstract class NewParametrized<K, V, M extends SomeParametrized<K, V>> { 

    public void someMethodThatTakesKAndV(K k1, V v1) { } 
} 

Другими словами, я хотел бы объявление класса выглядеть примерно так:

public class NewParametrized<M extends SomeParametrized<K, V>> { 

И К и типа V была бы быть выведено из определения М.

ответ

6

Проблема заключается в том, что K и V на самом деле не «повторяются», по крайней мере, не более чем объявление переменной и использование этой же переменной - «повторение».

Путь думать о том, что вы объявляете общие типы K и V, а затем использовать эти объявленные обобщенные типы в определении универсального типа M. Таким образом, вы не объявляете общий тип K или V более одного раза: скорее, вы объявляете каждый из них один раз, а затем ссылаетесь на них в объявлении чего-то еще.

Чтобы посмотреть на это по-другому, количество типовых типов здесь еще три, а именно K, V и M. M определяется в терминах K и V, но вам не нужно было определять M таким образом.


Я хотел бы добавить, что если вы являетесь сторонником type inference, вы можете просмотреть объявление и использование одной и той же переменной, как ненужного повторения. Однако, если вы привыкли программировать на Java (или C, или C++, или многие, многие другие языки), то вы, вероятно, привыкли к объявлению переменных перед их использованием.

+0

Я думаю, что он в основном означает повторение при использовании класса, а не только повторение в его объявлении. Каждый раз, когда вы ссылаетесь на экземпляр этого класса, вы должны повторять то же самое. Подобно 'NewParametrized >'. Оба экземпляра String/Integer являются использованиями, а не декларациями. –

+0

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

2

Если бы это было возможно, декларация

public class NewParametrized<M extends SomeParametrized<K, V>> { 

бы неоднозначным, если класс K или V были определены в том же пакете, было бы невозможно узнать, является ли переменная типа или ссылка конкретный класс.