gpt4 book ai didi

Scala:确定用于泛型的方法结果类型

转载 作者:行者123 更新时间:2023-12-01 01:43:51 25 4
gpt4 key购买 nike

在第三方库中有一系列的请求类,它们都派生自一些通用的基类,它是泛型的,以响应类为参数:

abstract class AbstractRequest[ResponseType] {

def execute(): ResponseType
}

class UserList {…}
class UserListRequest extends AbstractRequest[UserList] {…}

class Avatar {…}
class AvatarRequest extends AbstractRequest[Avatar] {…}



我想编写一些通用方法,它接受一个请求实例,以一些特殊的方式执行它几次,并将响应的处理委托(delegate)给参数中提供的函数:
def specialMultiExecute(request: Req)(responseHandler: Resp => Unit): Unit = …

- 被称为:
val myRequest: UserListRequest = …
specialMultiExecute(myRequest){ userList => … }

问题是我需要以某种方式指定 ReqResp specialMultiExecute 中的类型宣言。我尝试了明显的方法:
def specialMultiExecute[Req <: AbstractRequest[Resp], Resp](request: Req)(responseHandler: Resp => Unit): Unit = …

— 但 Scala 编译器无法扣除通用参数类型(需要显式规范,如 specialMultiExecute [UserListRequest, UserList] (myRequest){ userList => … })。

在这种情况下,在 C++ 中,我可以使用单个模板参数 Req 编写模板函数。 , 同时制作 Resp被确定为方法的结果类型 Req::execute :
template<typename Req>
void specialMultiExecute(
Req request,
std::function<void (decltype(std::declval<Req>().execute()))> responseHandler
) {…}
//i.e. we use `decltype(std::declval<Req>().execute())` instead of Resp

有没有办法写类似的东西是Scala?

我的意思是(在类似 Scala 的伪代码中):

def specialMultiExecute[Req <: AbstractRequest](request: Req)(responseHandler: ResultTypeOf(Req#execute) => Unit): Unit = ...

最佳答案

这是类型推断机制的限制。
解决它的最简单方法是使用隐含的证据 Req亚型 AbstractRequest[ResponseType] .

这是一个例子。

import scala.language.implicitConversions
import scala.reflect.runtime.universe.TypeTag

abstract class AbstractRequest[ResponseType] {
def execute(): ResponseType
}

final case class User(id: Int, name: String)
final case class House(id: Int, price: Int)

class UserListRequest extends AbstractRequest[List[User]] {
override def execute(): List[User] = List(User(id = 3, name = "Sasha"))
override def toString: String = "UserListRequest"
}

final class RequestWrapper[Req, Resp](val request: Req) extends AnyVal {
type ResponseType = Resp
}

implicit def request2wrapper[Req, Resp](request: Req)(implicit ev: Req <:< AbstractRequest[Resp]): RequestWrapper[Req, Resp] =
new RequestWrapper(request)

def specialMultiExecute[Req, Resp](wrapper: RequestWrapper[Req, Resp])
(responseHandler: wrapper.ResponseType => Unit)
(implicit ev: Req <:< AbstractRequest[Resp], TTReq: TypeTag[Req], TTResp: TypeTag[Resp]): Unit = {
val request: Req = wrapper.request
val executionResult: Resp = request.execute()
responseHandler(executionResult)
println(TTReq)
println(TTResp)
println(request)
}

specialMultiExecute(new UserListRequest())(println)
// List(User(3,Sasha))
// TypeTag[UserListRequest]
// TypeTag[List[User]]
// UserListRequest

Reference for <:<. Reference for "Dependent types".



编辑

修改了上面的代码示例以允许识别具体 RequestResponse正在使用的类型。

关于Scala:确定用于泛型的方法结果类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53419634/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com