如何在Scala中覆盖`org.elasticsearch.client.FilterClient#doExecute()`?(How to override `org.elasticsearch.client.FilterClient#doExecute()` in Scala?)

特别是"org.elasticsearch" % "elasticsearch" % "2.4.x" (它确实适用于ElasticSearch的更高版本,其中ActionRequest不再采用参数类型,但我们无法更新到那些!)。

我们试图覆盖的Java方法定义如下( 源代码 ):

protected <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) { in().execute(action, request, listener); }

天真的企图覆盖它......

import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { override def doExecute[ Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

...在我们尝试过的所有Scala版本中都失败了(2.11.11,2.11.12和2.12.4):

[info] Compiling 1 Scala source to /home/roberto/development/elasticsearch-scala-client-test/target/scala-2.11/classes ... [error] /home/roberto/development/elasticsearch-scala-client-test/src/main/scala/com/gu/DemoFilterClient.scala:7:101: type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]],Response <: org.elasticsearch.action.ActionResponse,RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder]] [error] override def doExecute[Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder]](action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response]) = super.doExecute(action, request, listener) [error] ^ [error] one error found

更清楚地列出编译器错误:

type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [ Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]], Response <: org.elasticsearch.action.ActionResponse, RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder] ]

请注意Request类型上的惊人递归声明!

示例sbt项目可在https://github.com/guardian/elasticsearch-scala-client-test获得

Specifically with "org.elasticsearch" % "elasticsearch" % "2.4.x" (it does work with later versions of ElasticSearch where ActionRequest no longer takes a parameter type, but we can't update to those just yet!).

The Java method we're trying to override is defined like this (source):

protected <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) { in().execute(action, request, listener); }

The naive attempt to override it...

import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { override def doExecute[ Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

...fails in all versions of Scala we've tried (2.11.11, 2.11.12, and 2.12.4):

[info] Compiling 1 Scala source to /home/roberto/development/elasticsearch-scala-client-test/target/scala-2.11/classes ... [error] /home/roberto/development/elasticsearch-scala-client-test/src/main/scala/com/gu/DemoFilterClient.scala:7:101: type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]],Response <: org.elasticsearch.action.ActionResponse,RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder]] [error] override def doExecute[Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder]](action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response]) = super.doExecute(action, request, listener) [error] ^ [error] one error found

To lay out that compiler error more clearly:

type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [ Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]], Response <: org.elasticsearch.action.ActionResponse, RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder] ]

Note that amazing recursive declaration on the Request type!

sample sbt project available at https://github.com/guardian/elasticsearch-scala-client-test

最满意答案

我遇到过你之前有这种F-bounded多态与原始Java类型的情况,如果我没记错的话,这样的东西应该可行(至少它在你的示例项目中编译):

package com.gu import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { type AR[x <: ActionRequest[x]] = ActionRequest[x] override def doExecute[ Request <: AR[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

看起来也应该可以使用forSome内联,但是我刚才尝试过的迭代都没有。

I've run into situations where you have this kind of F-bounded polymorphism with a raw Java type before, and if I remember correctly something like this should work (at least it compiles in your example project):

package com.gu import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { type AR[x <: ActionRequest[x]] = ActionRequest[x] override def doExecute[ Request <: AR[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

It seems like it should also be possible to do this inline with a forSome, but none of the iterations I've tried just now have worked.

如何在Scala中覆盖`org.elasticsearch.client.FilterClient#doExecute()`?(How to override `org.elasticsearch.client.FilterClient#doExecute()` in Scala?)

特别是"org.elasticsearch" % "elasticsearch" % "2.4.x" (它确实适用于ElasticSearch的更高版本,其中ActionRequest不再采用参数类型,但我们无法更新到那些!)。

我们试图覆盖的Java方法定义如下( 源代码 ):

protected <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) { in().execute(action, request, listener); }

天真的企图覆盖它......

import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { override def doExecute[ Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

...在我们尝试过的所有Scala版本中都失败了(2.11.11,2.11.12和2.12.4):

[info] Compiling 1 Scala source to /home/roberto/development/elasticsearch-scala-client-test/target/scala-2.11/classes ... [error] /home/roberto/development/elasticsearch-scala-client-test/src/main/scala/com/gu/DemoFilterClient.scala:7:101: type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]],Response <: org.elasticsearch.action.ActionResponse,RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder]] [error] override def doExecute[Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder]](action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response]) = super.doExecute(action, request, listener) [error] ^ [error] one error found

更清楚地列出编译器错误:

type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [ Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]], Response <: org.elasticsearch.action.ActionResponse, RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder] ]

请注意Request类型上的惊人递归声明!

示例sbt项目可在https://github.com/guardian/elasticsearch-scala-client-test获得

Specifically with "org.elasticsearch" % "elasticsearch" % "2.4.x" (it does work with later versions of ElasticSearch where ActionRequest no longer takes a parameter type, but we can't update to those just yet!).

The Java method we're trying to override is defined like this (source):

protected <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) { in().execute(action, request, listener); }

The naive attempt to override it...

import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { override def doExecute[ Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

...fails in all versions of Scala we've tried (2.11.11, 2.11.12, and 2.12.4):

[info] Compiling 1 Scala source to /home/roberto/development/elasticsearch-scala-client-test/target/scala-2.11/classes ... [error] /home/roberto/development/elasticsearch-scala-client-test/src/main/scala/com/gu/DemoFilterClient.scala:7:101: type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]],Response <: org.elasticsearch.action.ActionResponse,RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder]] [error] override def doExecute[Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder]](action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response]) = super.doExecute(action, request, listener) [error] ^ [error] one error found

To lay out that compiler error more clearly:

type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [ Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]], Response <: org.elasticsearch.action.ActionResponse, RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder] ]

Note that amazing recursive declaration on the Request type!

sample sbt project available at https://github.com/guardian/elasticsearch-scala-client-test

最满意答案

我遇到过你之前有这种F-bounded多态与原始Java类型的情况,如果我没记错的话,这样的东西应该可行(至少它在你的示例项目中编译):

package com.gu import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { type AR[x <: ActionRequest[x]] = ActionRequest[x] override def doExecute[ Request <: AR[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

看起来也应该可以使用forSome内联,但是我刚才尝试过的迭代都没有。

I've run into situations where you have this kind of F-bounded polymorphism with a raw Java type before, and if I remember correctly something like this should work (at least it compiles in your example project):

package com.gu import org.elasticsearch.action._ import org.elasticsearch.client.{Client, FilterClient} class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) { type AR[x <: ActionRequest[x]] = ActionRequest[x] override def doExecute[ Request <: AR[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder] ]( action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response] ) = super.doExecute(action, request, listener) }

It seems like it should also be possible to do this inline with a forSome, but none of the iterations I've tried just now have worked.