Kotlin中如何避免重复类名维护类属性名称列表?
不创建实例获取Kotlin类属性名称列表的简洁写法
在Kotlin里维护某个类(比如Car)的部分属性名称列表时,原始写法重复Car::和.name显得冗余,而用with(Car())的方式又会遇到实例化的限制——比如构造器私有、依赖过多或者创建成本高。这里有几个更优的解决方案:
方案1:顶层辅助函数统一处理属性引用
写一个通用的顶层函数,接收任意数量的属性引用,自动提取名称:
fun <T> propertyNames(vararg properties: KProperty1<T, *>): List<String> { return properties.map { it.name } } // 调用示例 val carPropertyNames = propertyNames( Car::model, Car::make, Car::company, Car::year, Car::power, Car::cylinders, Car::gearType, Car::seats, )
这种方式既省去了重复的.name,又完全不需要创建Car实例,类型安全且编译期就能校验属性是否存在。
方案2:在类的伴生对象中封装属性列表
如果想把属性列表的维护和Car类本身绑定,直接在伴生对象里写方法:
class Car(/* 构造参数 */) { var model: String = "" var make: String = "" var company: String = "" var year: Int = 0 var power: Int = 0 var cylinders: Int = 0 var gearType: String = "" var seats: Int = 0 companion object { fun getSelectedPropertyNames(): List<String> { return listOf( ::model, ::make, ::company, ::year, ::power, ::cylinders, ::gearType, ::seats, ).map { it.name } } } } // 调用示例 val carProps = Car.getSelectedPropertyNames()
伴生对象里的方法可以直接用::属性名引用当前类的属性,不用重复写Car::,同时完全避开实例化问题。
方案3:KClass扩展函数实现类上下文的简洁写法
如果想要更贴近with的语法风格但不创建实例,可以写一个inline扩展函数:
inline fun <reified T> KClass<T>.propertyNames(block: KClass<T>.() -> List<KProperty1<T, *>>): List<String> { return block().map { it.name } } // 调用示例 val carPropertyNames = Car::class.propertyNames { listOf( ::model, ::make, ::company, ::year, ::power, ::cylinders, ::gearType, ::seats, ) }
借助reified类型参数和KClass的上下文,在lambda里可以直接用::属性名,写法简洁且无需实例化。
这几个方案都解决了原始写法的冗余问题,同时避开了实例化带来的各种限制,根据自己的代码结构选择合适的即可。
内容的提问来源于stack exchange,提问作者Sadeq Dousti
相关产品推荐
相关产品推荐

