kotlin 委托
艺术源于生活:
interface Employee {
fun doWork(){}
}
class Me : Employee {
override fun doWork() {
println("Let's do it!")
}
}
class Leader(private val me: Me) : Employee {
override fun doWork() {
me.doWork()
}
}
这是一个最简单的委托模式,相信各位职场牛马都能轻松看懂。
上面的代码虽然通俗易懂,但写法有一点点繁琐,特别是接口有多个方法都需要委托的时候。我们可以使用 kotlin 关键字 by 稍做优化,减少不必要的 boilerplate code:
class Leader(private val me: Me) : Employee by me
更进一步,by 后面直接 new 出委托对象:
class Leader : Employee by Me()
至此,你应该已经学会 kotlin 的类委托啦!
Java 动态代理
好困🥱
学会了就要搞事情
作为资深 UI 开发工程师,各位平日里应该没少绘动画:
fun foo(anim: Animation) {
anim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationEnd(animation: Animation?) {
// continue...
}
override fun onAnimationStart(animation: Animation?) {
// I don't care!
}
override fun onAnimationRepeat(animation: Animation?) {
// I don't give a shit!
}
})
}
很多时候我们只关心动画结束,以便接着做其他事情。但是 Animation 库的设计者需要照顾所有使用者,得把可能用到的回调都给暴露出来。这样一来就会导致我们需要实现很多不关心的回调方法。
一种解决方案是先定义一个空实现类,后续用到的地方各自去重写自己关心的回调:
open class EmptyAnimationListener : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation?) {}
override fun onAnimationEnd(animation: Animation?) {}
override fun onAnimationRepeat(animation: Animation?) {}
}
fun foo(anim: Animation) {
anim.setAnimationListener(object : EmptyAnimationListener() {
override fun onAnimationEnd(animation: Animation?) {
// continue...
}
})
}
看起来只是稍好一点,毕竟 Animation.AnimationListener
仅有三个方法需要实现,要是换成 Application.ActivityLifecycleCallbacks
呢?
优雅的终极方案:
internal inline fun <reified T : Any> noOpDelegate(): T {
val javaClass = T::class.java
return Proxy.newProxyInstance(javaClass.classLoader, arrayOf(javaClass)) { _, _, _ ->
// no op
} as T
}
fun foo(anim: Animation) {
anim.setAnimationListener(object : Animation.AnimationListener by noOpDelegate() {
override fun onAnimationEnd(animation: Animation) {
// continue...
}
})
}
最后,都 4202 年了,写库的机灵鬼们,能不能把接口方法默认实现给加上,两大括号的事儿!