一.前言
平常我们可能面对这样一个场景:系统的某个接口有很多方法,而我们业务需要实现这个接口,真正需要的只有该接口的几个方法而已,但是又不得不重写实现该接口其他无用的方法,以至于产生了大量无用代码堆积,比如:
public interface Way {
void solve2();
void solve1();
void solve3();
void solve4();
}
/**
* 其实我们真正需要该接口的方法只有solve2,但是接口的其他三个接口还得重写
* 然后给个空实现,产生了无用代码堆积
*/
Way way = new Way() {
@Override
public void solve2() {
System.out.println("child solve2");
}
@Override
public void solve1() {
}
@Override
public void solve3() {
}
@Override
public void solve4() {
}
}
本篇文章主要是从Java和Kotlkotlin和javain的角度分别阐述怎么解决该痛点
二.Java优化接口实现
- 接口属于系统API或第三方库API定义
以上面的动画片少儿小猪佩奇
Way
为例,假如该接口是系统提供appreciate的,我们可以通过抽象类方式作为业务代码实现和系统接口的一个桥梁
定义一个抽象类,空实现Way
接口的全部方法:
public abstract class WayAdapter implements Way {
@Override
public void solve2() {
}
@Override
public void solve1() {
}
@Override
public void solve3() {
}
@Override
public void solve4() {
}
}
这样如果业务中再需要使用这个系统接口Way
的时候,我们不实现Way
直接继承上面类WayAdapter
,有选择性重写我们需要的方法,而无需额外处理其他非必须方法
@Test
public void main() {
Way way = new WayAdapter() {
@Override
public void solve2() {
}
};
}
Animationjava语言动画监听类
AnimatorListenerAdapter
就基于此
- 接口属于自身业务层定义
我们直接利用java8的
default
关键字来修改接口部分方法的定义方式:default在接口中修饰的方法可以直接在接口中就给出个空实现,子类不需要这个方法也不需要额外的重写
public interface Way {
void solve2();
default void solve1() {
}
default void solve3() {
}
default void solve4() {
}
}
如果
Way
接口强制要求sol动画专业ve2子类必须重写,其他方法可选,那我们直接给可选的方法使用default修饰给个空实现即可
@Test
public void main() {
Way way = new Way() {
@Override
public void solve2() {
}
};
}
Lifecycle的
DefaultLifecjava语言ycleObserve
就基于此
三.Kotlin优化接口实现
- 接口属于系统API或第三方库API定义
这种情况Koappointmenttlin有两种解决方式:
- 和上面java一样通过一个中间抽象类解决
interface Color {
fun alpha()
fun result()
fun process()
}
abstract class ColorAdapter: Color {
override fun alpha() {
}
override fun result() {
}
override fun process() {
}
}
- 通过Kotlin DSL的语法特性解决
//获取一个Color接口类型的对象
fun obtainColor(block: ColorAdapter.() -> Unit): Color {
return ColorAdapter().apply(block)
}
class ColorAdapter : Color {
private var alpha: (() -> Unit)? = null
private var result: (() -> Unit)? = null
private var process: (() -> Unit)? = null
fun setAlpha(block: () -> Unit) {
alpha = block
}
fun setResult(block: () -> Unit) {
result = block
}
fun setProcess(block: () -> Unit) {
process = block
}
override fun alpha() {
alpha?.invoke()
}
override fun result() {
result?.invoke()
}
override fun process() {
process?.invoke()
}
}
在业务需要的地方就可以如下这样使用:
//根据业务需要调用需要的setResult或setResult()或setProcess()方法
val color: Color = obtainColor {
setResult {
//todo 实现具体的代码逻辑
}
}
- 接口属于自身业务层定义
这种方式实现也基本和java的方式一样,区别在于kotlin不用加
default
interface Color {
fun alpha() {
}
fun result() {
}
fun process()
}
使用:
val color2: Color = object : Color {
override fun process() {
}
}
四.彩蛋(题外话)
Kotlin下如果需要定义一个函数动画专业式接口(只包含一个方法的接口),Kotlin有两种方式:
- 如果想要实现SAM转换,则kotlin接口定义的时候需要前面加个
fun
关键字(kotlin1.appstore4才开始有)
fun interface Tree {
fun num()
}
- 直接利用Kotlin特有的函数类型,而无需定义接口:
var listen: ((View) -> Unit)? = null