我是 Kotlin 新手,正在调查什么是可能/不可能的
我有一个用例如下:-
作为一项技术练习,我尝试对远程 API 请求和响应进行建模,并加强它们之间的关系
我的目标是能够在类的顶部以清晰简洁的方式声明请求和响应之间的关系。这将 1)。记录该类进行的 API 调用,2)。强制执行关系,使 Request1 只能生成 Response1
伪代码:-
Requests {
Request1 -> Response1
Request2 -> Response2
...
RequestN -> ResponseN
}
我定义了两个接口(interface)Request
和Response
并按如下方式使用它们:-
interface Request {
fun <T> response(data : T): Lazy<Response>
}
interface Response
data class Request1(val request: String) : Request {
data class Response1(val output: String) : Response
override fun <T> response(data: T): Lazy<Response> {
return lazy { Response1(data as String) }
}
}
data class Request2(val request: Long) : Request {
data class Response2(val output: Double) : Response
override fun <T> response(data: T): Lazy<Response> {
return lazy { Response2(data as Double) }
}
}
我有一个 Controller 类,它按如下方式进行 API 调用:-
class Controller {
fun call(request: Request): Lazy<Response> {
return when (request) {
is Request1 -> request.response("Testing Data")
is Request2 -> request.response(Math.PI)
else -> TODO()
}
}
}
使用上述数据类,我可以强制将 Request1
仅链接到 Response1
,并指定每个 Response 包装的响应数据类型。
虽然上述类提供了功能并遵守这些规则,但它们很冗长。
我可以采用更简洁的方法来获得所需的结果吗?
我需要这个的原因是我正在寻找“自记录”代码,开发人员可以在其中查看请求/响应对和关联规则的定义并清楚地了解其意图。
例如:查看最终请求定义的开发人员可以清楚地看到 Response1 是由 Request1 生成的。我还想强制执行 Response1 只能从 Request1 生成。
我上面的例子是简化的,因为在“现实世界”中,每个响应包装的数据将来自实际的 API 请求调用,我已经用“硬编码”进行了说明。
如果可能的话,我宁愿在一行上定义 Request1 和 Response1。
更新
我已经重构了我原来的类如下:-
interface Request<ResponseData> {
fun response(data: ResponseData): Lazy<Response>
}
interface Response
sealed class Requests<T> : Request<T> {
data class Request1(val request: String) : Requests<String>() {
inner class Response1(val output: String) : Response
override fun response(data: String): Lazy<Response> {
return lazy { Response1(data) }
}
}
data class Request2(val request: Long) : Requests<Double>() {
inner class Response2(val output: Double) : Response
override fun response(data: Double): Lazy<Response> {
return lazy { Response2(data) }
}
}
}
class Controller {
fun <T> call(request: Request<T>): Lazy<Response> {
return when (request) {
is Requests.Request1 -> request.response("Testing Data")
is Requests.Request2 -> request.response(Math.PI)
else -> TODO()
}
}
}
虽然我的代码的这个版本比原始代码有很多好处,但我仍然不满意的一个功能是每个请求/响应声明仍然非常冗长,例如它需要 5 行代码。我可以采用一种方法来使每个请求/响应对声明更加简洁吗?占用更少的代码行。
更新二
我正在尝试重构上面的密封类,以便在外部密封类中定义重写的函数response
。
interface Request<ResponseData> {
fun response(data: ResponseData): Lazy<Response>
}
interface Response
sealed class Requests<T> : Request<T> {
data class Request1(val request: String) : Requests<String>() {
inner class Response1(val output: String) : Response
}
data class Request2(val request: Long) : Requests<Double>() {
inner class Response2(val output: Double) : Response
}
override fun response(data: T): Lazy<Response> {
return lazy { // What implementation goes here??? // }
}
}
这种方法可行吗?
如何引用外部密封类中的各个具体 ResponseN
类?
最佳答案
另一种方法:
data class Box<T, V>(val req: T, val rsp: V)
interface Interaction<RequestT, ResponseT> {
val req: RequestT
fun exec(): Box<RequestT, ResponseT>
}
sealed class Interactions<RequestT, ResponseT> : Interaction<RequestT, ResponseT> {
class Interaction1(override val req: String) : Interaction<String, String> {
override fun exec() = Box(req, "by")
}
class Interaction2(override val req: Long) : Interaction<Long, Double> {
override fun exec() = Box(req, 1.0)
}
}
fun main() {
val interaction1 = Interactions.Interaction1("hi")
val interaction2 = Interactions.Interaction2(42)
println(interaction1.exec()) // Box(req=hi, rsp=by)
println(interaction2.exec()) // Box(req=42, rsp=1.0)
}
关于kotlin - 如何强制 Kotlin 类之间的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66708339/