使用Kotlin开发Android应用(III):扩展函数和默认值
通过前面两篇文章,我们学习了Kotlin的基本知识,并知道如何配置工程,本文将接着介绍Java没有的而Kotlin实现了的有趣的特性。记住当你对Kotlin语言有任何疑问时,请参考官方指南。该指南组织的很好,而且容易理解,本文将不会介绍语言的基本知识。
扩展函数
Kotlin的扩展函数功能使得我们可以为现有的类添加新的函数,而不用修改原来的类。例如,我们可以为一个activity添加一个新函数,用于显示一个toast:
fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT){?
Toast.makeText(this, message, duration)?.show()
}
我们可以在任何地方声明这个函数(例如在一个utils文件中),然后像使用普通函数一样在这个activity中使用它:
override fun onCreate(savedInstanceState: Bundle?) {
super<BaseActivity>.onCreate(savedInstanceState)?
toast("This is onCreate!!")?
}
声明一个扩展函数很简单,只需要在函数名之前添加指定的类名即可。在调用时,该函数会以导入的方式添加到这个类中。
扩展函数帮助我们简化代码,并极大的利用封闭的类。不过我们要小心并且不过度使用它。使用扩展函数的一个结果是它通常用于替代工具类。工具函数是静态的而且不能被mocked,因此过度使用工具函数通常是我们懒得创建托管类的结果。
下面是另一个有趣的例子,用于解释另一个有趣的概念:具体化(reified)类型。
inline public fun <reified T : Activity> Activity.navigate(id: String) {?
val intent = Intent(this, javaClass<T>())
? intent.putExtra("id", id)
? startActivity(intent)?
}
内联函数可以使用具体化(reified)类型,这意味着我们可以在一个函数内部通过类型来恢复一个类,而不是将类的类型作为一个参数传入。
內联函数和普通函数有一点区别。內联函数在编译期间会进行代码替换,而不是真的进行函数调用。在某些情况下可以简化问题。例如,如果我们有一个函数会作用参数进行传递,普通函数会在内部创建一个包含这个函数的对象;而內联函数将会在函数被调用的地方使用代码直接替换函数调用,因此不需要创建一个内部对象。
navigate<DetailActivity>("2")
使用reified类型,我们可以在一个函数内部创建一个intent,并使用扩展函数,这样我们可以直接调用startActivity()。
可选参数和默认值
借助于参数和构造函数的默认值,你将不再需要进行函数重载了。一个函数声明就可以满足你所有的需求。让我们回到toast的例子:
fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT){?
Toast.makeText(this, message, duration)?
}
第二个参数表示toast的显示持续时间,这是一个可选参数,但没有显式指定时,将使用默认的Toast.LENGTH_SHORT。因此,你有两种方式调用这个函数:
toast("Short Toast!!")
toast("Long Toast!!", Toast.LENGTH_LONG)
回到前面第二个例子,我们可能想要增加几个参数来支持lollipop动画:
inline public fun <reified T : Activity> Activity.navigate(
? id: String,?
sharedView: View? = null,
? transitionName: String? = null) {??
...
现在我们有两种方式调用同一个函数:
navigate<DetailActivity>("2")
navigate<DetailActivity>("2", sharedView, TRANSITION_NAME)
甚至还有第三种方式,在这种情况下意义不大,但有助于帮助我们理解另一个概念:我们可以使用参数名字来决定哪个参数会被调用:
navigate<DetailActivity>(id = "2", transitionName = TRANSITION_NAME)
可选参数也可以被用在默认构造函数中,因此,你可以只声明一个构造函数,但会得到很多重载。自定义views是一个特殊例子,在Java中它们需要多于一个构造函数以便正确的运行,我会在下一篇文章中进行介绍。
总结
使用扩展函数以及可选参数和默认值,我们可以节省很多代码,甚至完成在Java中无法做到的事情。Kotlin真的更具表达性而且简洁。下一篇文章将会介绍Kotlin的Android扩展,它使得我们可以在activities中自动注入views,同时也会介绍使用Kotlin创建自定义views。
请记得查看实际运行我们的Demo例子,实践出真知。
文末摄影鉴赏