kotlin - 如何强制 Kotlin 类之间的关系

标签 kotlin

我是 Kotlin 新手,正在调查什么是可能/不可能的

我有一个用例如下:-

作为一项技术练习,我尝试对远程 API 请求和响应进行建模,并加强它们之间的关系

我的目标是能够在类的顶部以清晰简洁的方式声明请求和响应之间的关系。这将 1)。记录该类进行的 API 调用,2)。强制执行关系,使 Request1 只能生成 Response1

伪代码:-

Requests {
  Request1 -> Response1   
  Request2 -> Response2
  ...   
  RequestN -> ResponseN
}

我定义了两个接口(interface)RequestResponse并按如下方式使用它们:-

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/

相关文章:

postgresql - Spring Boot+Kotlin+Postgres 和 JSON : "org.hibernate.MappingException: No Dialect mapping for JDBC type"

flutter - 当我将 better_player flutter 包添加到 pubspec.yaml 中的依赖项时,应用程序无法运行

android - 我的布局文件没有显示在 setContent(R.layout.xml 文件)..?

android - 为什么 Recycler View 提供比 List View 更好的体验?

android - org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException : Descriptor wasn't found for declaration SCRIPT 问题

for-loop - kotlin,如何动态改变for循环的速度

java - android中cardview中的Clickable false无法工作

android - Kotlin + Dagger - 为 ViewModel 工厂注入(inject) Map

java - Avro 使用 json 转换生成类问题 [kotlin]

java - 标准 Kotlin 库中有哪些 Java 8 Stream.collect 等效项?