Kotlin仅用函数封装传递数据的更优实现方案问询
仅用函数封装Person数据的优化方案咨询
出于兴趣用Kotlin开展编程实验,目标为仅通过函数(禁止使用类与数据类)封装并传递数据,已完成一种基于函数构造器的Person数据存储实现,代码如下:
// I've created a function structure that allows me to keep data of a "Person" in memory: package org.example typealias InvocableParameter = (String) -> (() -> Any?)? fun personConstructor( name: String, age: Int, mother: InvocableParameter = { null }): InvocableParameter { return { parameter: String -> when (parameter) { "name" -> { name } "age" -> { age } "mother" -> { mother } "toJson" -> { "{ \"name\": \"$name\", \"age\": $age }" } else -> null } } } fun main() { val johnObject = personConstructor( "john", 20, personConstructor( "Lory", 40, personConstructor("Eva", 60) ) ) println(johnObject("toJson")?.invoke()) val johnsMother = johnObject("mother")?.invoke() as InvocableParameter val johnsGrandma = (johnsMother.invoke("mother")?.invoke()) as InvocableParameter println(johnsMother.invoke("toJson")?.invoke()) println(johnsGrandma.invoke("toJson")?.invoke()) } // Outputs: // { "name": "john", "age": 20 } // { "name": "Lory", "age": 40 } // { "name": "Eva", 60 }
现咨询是否有更简洁优雅的实现方式达成该目标。
优化后的实现方案
可以从简化类型定义、减少冗余调用、提升可读性与类型安全性几个方向优化,以下是几种更简洁的实现思路:
1. 简化核心类型与访问逻辑
原实现的嵌套函数调用冗余度高,可将类型简化为直接返回值的函数,避免额外的invoke()调用:
package org.example typealias Person = (String) -> Any? fun person( name: String, age: Int, mother: Person = { null } ): Person = { key -> when (key) { "name" -> name "age" -> age "mother" -> mother "toJson" -> """{"name": "$name", "age": $age}""" else -> null } } fun main() { val john = person( "john", 20, person("Lory", 40, person("Eva", 60)) ) println(john("toJson")) val johnsMother = john("mother") as Person val johnsGrandma = johnsMother("mother") as Person println(johnsMother("toJson")) println(johnsGrandma("toJson")) }
关键优化:
- 将类型别名重命名为语义化的
Person,提升可读性 - 直接返回属性值而非嵌套无参函数,访问时无需额外
?.invoke() - 使用Kotlin三重引号简化JSON字符串的转义操作
2. 基于映射的可扩展实现
如果需要新增属性,可将属性映射逻辑提取到Map中,避免修改when分支,提升扩展性:
package org.example typealias Person = (String) -> Any? fun person( name: String, age: Int, mother: Person = { null } ): Person { val props = mapOf( "name" to name, "age" to age, "mother" to mother, "toJson" to """{"name": "$name", "age": $age}""" ) return { props[it] } } // 调用逻辑与上述main函数一致
这种方式下,新增属性只需在props中添加键值对即可,无需改动核心逻辑。
3. 类型安全的访问封装
为避免频繁的强制类型转换,可封装泛型访问函数,提升类型安全性与代码简洁度:
package org.example typealias Person = (String) -> Any? fun person( name: String, age: Int, mother: Person = { null } ): Person = { key -> when (key) { "name" -> name "age" -> age "mother" -> mother "toJson" -> """{"name": "$name", "age": $age}""" else -> null } } inline fun <reified T> Person.get(key: String): T? = this(key) as? T fun main() { val john = person( "john", 20, person("Lory", 40, person("Eva", 60)) ) println(john.get<String>("toJson")) val johnsMother = john.get<Person>("mother") val johnsGrandma = johnsMother?.get<Person>("mother") println(johnsMother?.get<String>("toJson")) println(johnsGrandma?.get<String>("toJson")) }
关键优化:
- 通过泛型函数
get封装类型转换,避免直接as强制转换,减少类型转换异常风险 - 调用时通过
get<String>或get<Person>明确类型,代码可读性更强
以上方案均严格遵循"仅用函数封装数据"的要求,同时在简洁性、可读性与扩展性上有明显提升。
内容的提问来源于stack exchange,提问作者Arthur Frade
相关产品推荐
相关产品推荐

