Kotlin中如何实现仅约束filter返回值为Boolean的抽象Filter接口
你对接口的定义和里氏替换原则的理解存在偏差,你想要的抽象可以通过泛型接口或者Kotlin函数类型实现。
问题根源
- 接口的方法签名包含参数列表、返回值类型、方法名三部分,子类重写方法必须和父类接口的签名完全匹配,你定义的
Filter接口中filter()是无参方法,子类自然不能加参数实现。 - 你的初始设计也不符合里氏替换原则:如果超类型
Filter支持无参调用filter(),那所有子类型都必须支持无参调用该方法,否则你用Filter类型接收实例后,无法正常调用方法,子类型不能替换超类型的使用场景,就违反了该原则。
实现方案
方案1:带泛型的Filter接口
如果需要统一的Filter接口标识,可通过泛型绑定不同实现的入参类型:
- 单参数场景:
// 泛型P表示入参类型 fun interface Filter<P> { fun filter(param: P): Boolean }
- 多参数场景可以把参数封装为单独的数据类,也可以定义多泛型参数的接口:
// 双参数Filter接口 fun interface BiFilter<P1, P2> { fun filter(p1: P1, p2: P2): Boolean }
你的LocationFilter可按如下方式实现,也支持你原本想用的伴生对象写法:
data class Coordinate(val x: Double, val y: Double) class LocationFilter { companion object : BiFilter<Coordinate, Coordinate> { override fun filter(coord1: Coordinate, coord2: Coordinate): Boolean { TODO("此处编写业务逻辑") } } }
方案2:直接使用Kotlin函数类型
如果不需要统一的接口标识,仅需要约束「返回值为Boolean」,直接用对应参数的函数类型即可,Kotlin原生支持该特性:
// 直接声明符合要求的函数类型实例 val locationFilter: (Coordinate, Coordinate) -> Boolean = { coord1, coord2 -> TODO("业务逻辑") }
使用时直接调用locationFilter(coordA, coordB)即可,和普通方法没有区别。
内容的提问来源于stack exchange,提问作者Jared Rieger
相关产品推荐
相关产品推荐

