Kotlin函数返回匿名对象的类型推导及泛型惯用写法问题
匿名对象返回类型的自动推断规则
Kotlin对匿名对象的类型推断有明确限制:
- 只有当函数为私有(private) 或局部函数时,返回的匿名对象的实际类型才会被保留,自定义的
with方法可以被正常识别 - 若函数为公有、保护、内部修饰的,返回的匿名对象类型会被自动向上擦除为
Any,无法识别到匿名对象内部的自定义方法
如果having函数只需要在当前文件/当前类内部使用,只要给函数加上private修饰即可直接解决类型识别问题,不需要单独抽取独立类。另外注意Class.newInstance()在高版本Kotlin/Java中已被废弃,推荐替换为getDeclaredConstructor().newInstance()兼容无参构造场景。
泛型写法的优化建议
当前传入Class<T>的写法是Java的惯用实现,Kotlin更推荐使用实化类型参数(reified) 优化,不需要手动传入类对象,DSL调用会更简洁:
// 搭配inline + reified 不需要传Class参数 private inline fun <reified T> having() = object { infix fun with(fn: T.() -> Unit) = T::class.java.getDeclaredConstructor().newInstance().apply(fn) } fun test() { // 调用时直接指定泛型即可,无需传入::class.java having<Pizza>() with { size = Size.NORMAL cheese = Cheese.MOZARELLA } }
如果模型类均包含公开无参构造,上述写法可满足需求。如果不想依赖反射实现,更推荐无反射的通用Builder写法,完全符合Kotlin惯用规范,无额外性能开销:
inline fun <T> build(instance: T, fn: T.() -> Unit): T = instance.apply(fn) // 调用示例 fun test() { build(Pizza()) { size = Size.NORMAL cheese = Cheese.MOZARELLA } }
内容的提问来源于stack exchange,提问作者Tuomas Toivonen
相关产品推荐
相关产品推荐

