Как вы пишете дженерики подклассов? - PullRequest
0 голосов
/ 27 января 2019

Хорошо, поэтому я пытаюсь использовать Volley для реализации клиента для сервера RESTful.

У меня есть IServerRequest и IServerResponse доменные объекты.

Теперь я хочу написать IServerRequestVisitor, который превращает IServerRequest s в запрос Volley.

Теперь залп Request<ResponseType> возьмет NetworkResponse и попытается разобрать его в ResponseType.Затем требуется набор из двух слушателей:

Response.Listener<ResponseType>, который вызывается, когда запрос успешно анализирует ответ.

Response.ErrorListener, если это не так.

Таким образом, я представлял себе следующее:

У меня есть

class VolleyRequestDispatcher(
        private val context:Context
):IServerRequestVisitor<VolleyResponseListeners<IServerResponse>,Unit> {...}

, который реализует интерфейс IServerRequestVisitor.На данный момент есть только один тип запроса, который необходимо обработать, но нужно добавить еще.

interface IServerRequestVisitor<in Params, out ReturnType>{
    fun visit(req: ILoginRequest, params:Params):ReturnType
}

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

data class VolleyResponseListeners<ResponseType>(
        /**Called IFF the corresponding [Request] succeeds in parsing its [Response]*/
        val onResponse:Response.Listener<ResponseType>,

        /**Called if there was an error parsing the [Response]*/
        val onError: Response.ErrorListener
)

Пока все хорошо.Давайте создадим

class VolleyLoginRequest(
        serverURL:String,
        private val loginRequest:ILoginRequest,
        private val listener:Response.Listener<ILoginResponse>,
        errorListener:Response.ErrorListener
): Request<ILoginResponse>(Method.POST,"$serverURL/login",errorListener){...}

НО , если я сейчас пойду к своему VolleyRequestDispatcher и напишу

override fun visit(req: ILoginRequest, params:VolleyResponseListeners<IServerResponse>){
    val serverURL = WebConfig.getServerURL()
    val request = VolleyLoginRequest(serverURL,req,params.onResponse,params.onError)
    //dispatch the request
}

AndroidStudio жалуется, что params.onResponse имеет тип Response.Listener<IServerResponse>, когда я указал в своем VolleyLoginRequest, что мне нужен слушатель типа Response.Listener<ILoginResponse>.

Теперь, очевидно, ILoginResponse является подтипом IServerResponse.Так что это заставляет меня думать, что я должен быть в состоянии отбросить несколько in или out с в соответствующих местах, чтобы выполнить эту работу.

Пока, однако, я не мог понять, где это было.

Буду признателен, если кто-нибудь поможет мне с этим.

(И да, я знаю знаю, что я могу просто изменить VolleyLoginRequest требовать Response.Listener<IServerResponse>, а затем ожидать, что клиент выполнит проверку типов и произнесет прослушиватель, но я бы предпочел этого не делать.)

...