关闭

使用Kotlin开发Android应用(III):扩展函数和默认值

标签: androidkotlin
5047人阅读 评论(2) 收藏 举报
分类:

使用Kotlin开发Android应用(III):扩展函数和默认值

@author ASCE1885的 Github 简书 微博 CSDN
原文链接

通过前面两篇文章,我们学习了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例子,实践出真知。

文末摄影鉴赏

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:905511次
    • 积分:12483
    • 等级:
    • 排名:第1108名
    • 原创:254篇
    • 转载:0篇
    • 译文:38篇
    • 评论:244条
    博客专栏
    最新评论