如何在实例化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
相关产品推荐
相关产品推荐

