You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在实例化Kotlin数据类时复用参数值且避免重复调用方法?

问题描述

我定义了一个data class MyDTO,它接收多个参数。在一处调用该类的场景中,部分参数的取值相同。目前我使用如下函数来创建该类的实例:

fun createDTO(f: Foo): MyDTO {
    val a = f.foo()
    val b = f.bar()
    val c = f.baz()
    return MyDTO(a, a, b, c, b, c)
}

我希望能用更简洁的方式实现这一逻辑,尤其偏好表达式体写法,但无法直接写成:

fun createDTO(f: Foo) = MyDTO(f.foo(), f.foo(), f.bar(), f.baz(), f.bar(), f.baz())

因为foo、bar和baz方法执行成本较高或存在副作用,因此只能调用一次。我曾尝试类似如下的写法:

data class MyDTO(val x1: Int, val x2: Int, val y1: Int, val y2: Int, val z1: Int, val z2: Int)

fun createDTO(f: Foo) = MyDTO(f.foo(), x2, f.bar(), f.baz(), y1, y2)

但显然,在完成实例创建前无法访问MyDTO的属性。请问是否有更简洁的实现方式?

解决方案

1. 用run函数实现表达式体

借助Kotlin的run作用域函数,能在表达式体内一次性计算所有变量,既满足简洁性要求,又保证每个方法只调用一次:

fun createDTO(f: Foo) = run {
    val a = f.foo()
    val b = f.bar()
    val c = f.baz()
    MyDTO(a, a, b, c, b, c)
}

这种写法和原代码逻辑完全一致,同时保持了表达式体的简洁形式。

2. 解构声明(需修改Foo类)

如果有权限调整Foo类,可以给它添加解构声明的operator方法,进一步简化代码:

class Foo {
    fun foo() = 1
    fun bar() = 2
    fun baz() = 3

    operator fun component1() = foo()
    operator fun component2() = bar()
    operator fun component3() = baz()
}

fun createDTO(f: Foo) = f.run { val (a, b, c) = this; MyDTO(a, a, b, c, b, c) }

3. 扩展函数封装逻辑

如果该创建逻辑会被多次使用,给Foo添加扩展函数是更符合Kotlin风格的做法:

fun Foo.toMyDTO(): MyDTO {
    val a = foo()
    val b = bar()
    val c = baz()
    return MyDTO(a, a, b, c, b, c)
}

// 调用示例
fun someUsage(f: Foo) {
    val dto = f.toMyDTO()
}

内容的提问来源于stack exchange,提问作者k314159

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:55:07