2013-03-27 4 views
8

Я пытаюсь выяснить, как получить дженерики, чтобы прыгать через обручи.Generics Puzzler

у меня есть:

interface Root { } 
interface Middle extends Root { } 
class Type implements Root { } 

И много "подтип" классы:

class Subtype1 extends Type implements Middle { } 
class Subtype2 extends Type implements Middle { } 
... 

То, что я хочу, чтобы объявить класс с двумя параметрами типа T и S, где T она связана Type и S связан T и Middle.

Я не вижу способа с дженериками, чтобы гарантировать, что S расширяет T И реализует Middle. То, что я хочу что-то вроде:

class Handler<T extends Root, S extends T, S extends Middle>; 

или

class Handler<T extends Root, S extends <T extends Middle>>; 

Но, конечно, ни законны. Может быть, есть какая-то магия, которой я не хватает?

+2

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

+2

related: http://stackoverflow.com/a/13261667/697449 –

+0

Спасибо. Это тоже было мое чтение, но я понял, что возможно, что у меня что-то не хватает в спецификации. Бросает! –

ответ

2

Попробуйте ввести абстрактный класс, который расширяет SubType и реализует Middle, поэтому его тип может использоваться в Handler.

abstract class MiddleSubtype extends Subtype implements Middle { } 

Затем

class Handler<T extends Root, S extends MiddleSubtype> { //... 

EDIT: После обновления на вопрос, та же идея будет выглядеть так:

abstract class MiddleType extends Type implements Middle { } 

class Subtype1 extends MiddleType { } 
class Subtype2 extends MiddleType { } 
... 

class Handler<T extends Root, S extends MiddleType> { //... 
+1

Обратите внимание, что это отличается от 'T extends Root, S extends T ...', хотя, поскольку 'S' больше не связывается' T'. –

+0

Да и он привязывает обработчик к одному подтипу. На самом деле у меня есть куча подтипов, что означало бы кучу обработчиков, и именно этого я и старался избежать. –

+0

@NickPalmer См. Мое редактирование этого ответа. Я думаю, что это близко к тому, что предлагал rgettman. –

0

Или вы могли бы сделать S родовое себя:

interface SInt<A,B> {} 
class Handler<T extends Root, S extends SInt<T, Middle>>{}