2015-02-06 2 views
0

Я пытаюсь написать общий интерфейс для моей базовой службы. Вот что я пробовал вообще:Как использовать generics generics в java-интерфейсах

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

abstract class Response { 

}  

abstract class Request<R extends Response> { 

} 

Теперь давайте напишем несколько реализаций о них:

class DummyResponse extends Response { 

} 

class DummyRequest extends Request<DummyResponse> { 

} 

Хорошо, у нас есть реализации. Давайте углубимся в интерфейс, где я боролся:

interface MyService { 

    <R extends Response, T extends Request<R>> R getResponse(T request); 

} 

Когда я реализую эту MyService, я получил ошибки:

class MyServiceImpl implements MyService { 

    //these method gives me error 
    @Override 
    public DummyResponse getResponse(DummyRequest request) { 
     //do sth 
     return response; 
    } 

} 

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

Как это сделать с использованием интерфейсов? Или это неправильный подход? Каков истинный способ сделать это?

Заранее спасибо.

ответ

4

Чтобы правильно реализовать интерфейс MyService, вы должны указать общий метод getResponse, который соответствует параметрам типа. Тем не менее, вы неявно размещаете аргументы типа DummyResponse и DummyRequest, и вы не объявляете параметры типа R и T как MyServicegetResponse метод делает.

Решение здесь заключается в перемещении параметров типа R и T на интерфейс.

interface MyService<R extends Response, T extends Request<R>> { 
    R getResponse(T request); 
} 

Тогда MyServiceImpl может поставить аргументы типа для MyService при его реализации, и getResponse может использовать эти аргументы типа для успешного применения метода getResponse.

class MyServiceImpl implements MyService<DummyResponse, DummyRequest> { 

    // This now implements MyService correctly. 
    @Override 
    public DummyResponse getResponse(DummyRequest request) { 
     //do sth 
     return response; 
    } 

} 
+0

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

+2

Подумайте об этом на уровне. Если интерфейс говорит, что разработчики должны предоставить метод, который принимает любую действительную комбинацию R и T, как это реализация этого интерфейса для создания класса, который принимает только одну конкретную комбинацию? Java-дженерики не являются инструментом шаблонов, забудьте теперь, что синтаксис выглядит одинаково, и вы сэкономите много разочарований. – Affe

+2

@oko Проблема в том, что если генераторы должны существовать в методе в интерфейсе, тогда все конкретные классы должны иметь общие элементы для метода реализации. Все конкретные классы должны были бы использовать любой «ответ» и любой «запрос», который связывается с ним. Конструкция общего метода на не-общий интерфейс здесь неверна; правильный дизайн с общим интерфейсом. – rgettman