Kotlin中如何获取方法参数的精确类型并访问对应属性?
解决方案
方案1:抽象公共属性(优先推荐)
这是最符合面向对象设计的方案,从根源上避免重复的类型判断:
如果可以修改父类BasicListItem,直接将两个子类共有的title、description属性提升到父类中声明:
open class BasicListItem( open val title: String, open val description: String ) // 子类继承父类,重写对应属性即可 data class Post( override val title: String, override val description: String, // Post 独有属性 val author: String ) : BasicListItem(title, description) data class Review( override val title: String, override val description: String, // Review 独有属性 val rating: Int ) : BasicListItem(title, description)
改造后不需要任何类型判断,直接在方法中访问父类属性即可:
fun setupListItemViews(item: BasicListItem) { item_title.text = item.title item_descr.text = item.description // 若需要处理子类独有属性,配合Kotlin智能转换即可 when(item) { is Post -> item_sub.text = "作者:${item.author}" is Review -> item_sub.text = "评分:${item.rating}星" } }
如果无法修改父类BasicListItem的定义,可以抽离公共接口让两个子类实现:
interface IListItemDisplay { val title: String val description: String } data class Post(/*原有属性*/) : BasicListItem(), IListItemDisplay data class Review(/*原有属性*/) : BasicListItem(), IListItemDisplay
方法参数可直接使用IListItemDisplay类型,同样可以直接访问公共属性。
方案2:封装类型判断工具(适合无法修改类结构的场景)
如果不能修改父类和子类的定义,可以封装通用的类型处理工具,避免多个方法重复写类型判断逻辑:
首先写一个高阶扩展函数统一处理类型分发:
inline fun <R> BasicListItem.runByType( onPost: (Post) -> R, onReview: (Review) -> R ): R = when(this) { is Post -> onPost(this) is Review -> onReview(this) else -> throw IllegalArgumentException("不支持的列表项类型:${javaClass.simpleName}") }
所有需要区分类型的方法直接调用该工具即可,不需要重复写类型判断:
fun setupListItemViews(item: BasicListItem) { item.runByType( onPost = { post -> item_title.text = post.title item_descr.text = post.description // 处理Post专属逻辑 }, onReview = { review -> item_title.text = review.title item_descr.text = review.description // 处理Review专属逻辑 } ) }
如果仅需要访问公共属性,也可以直接封装扩展属性,进一步简化调用:
val BasicListItem.title: String get() = when(this) { is Post -> this.title is Review -> this.title else -> "" } val BasicListItem.description: String get() = when(this) { is Post -> this.description is Review -> this.description else -> "" }
封装后直接调用item.title、item.description即可,不需要任何额外判断。
内容的提问来源于stack exchange,提问作者G. Rann
相关产品推荐
相关产品推荐

