❝ 本文将介绍 Kotlin 中的扩展函数和扩展属性,并用这两个特性来逐步优化代码的写法,希望大家学习这种特性并在实践当中做更多的扩展。

在 Android 开发中,大家可能经常使用这样的代码来判断或设置视图的可见性:

if (view.getVisibility() == View.VISIBLE) {view.setVisibility(View.GONE);// ...
}

或者封装了一个 px 转 dp 的工具类,如果计算逻辑比较复杂,可能会写成这样:

int width = (textView.getWidth() + DisplayUtils.dp2px(40)) / 2 - DisplayUtils.dp2px(18);

如果在一行代码中 DisplayUtils.dp2px() 工具类使用非常多的话代码会很长,也会增加理解难度。

那么,如果使用 Kotlin 中的扩展函数或扩展属性去精简一下,就可以方便很多。下面来介绍一下。

1. 扩展函数

所谓扩展函数,就是对一个现有类扩展定义一个成员函数,不过该定义在类的外面。一般我们如果想对一个类封装一个 API 方法,但又不能直接修改该类时,就可以用到扩展函数。

扩展方法的一般格式如下:

fun 类名.方法名([参数 1, 参数 2, ...]): 返回类型 {方法体
}

下面,我们将判断或设置视图的可见性封装成扩展方法,并定义在一个 kt 文件的最外层:

// ViewExtensions.kt
fun View.isVisible(): Boolean {return visibility == View.VISIBLE
}fun View.setVisible(visible: Boolean) {visibility = if (visible) View.VISIBLE else View.GONE
}

在扩展方法中,可以使用这个类的公有的方法和属性,例如上面代码中的 getVisibility()setVisibility()

之后,在 Kotlin 代码中所有的 View 类及它的子类都可以用这两个方法了:

if (view.isVisible()) {view.setVisible(false)// ...
}

下面我们来看看扩展方法转换成 Java 代码是什么样的:

public final class ViewExtensionsKt {public static final boolean isVisible(@NotNull View $this$isVisible) {Intrinsics.checkParameterIsNotNull($this$isVisible, "$this$isVisible");return $this$isVisible.getVisibility() == 0;}public static final void setVisible(@NotNull View $this$setVisible, boolean visible) {Intrinsics.checkParameterIsNotNull($this$setVisible, "$this$setVisible");$this$setVisible.setVisibility(visible ? 0 : 8);}
}

可以看出来转成 Java 代码后,将这个要扩展的类换成静态方法的第一个参数了,而原扩展方法的参数列表变成了从第二个参数开始定义,因此,我们可以按如下方式在 Java 中使用该扩展方法:

if (ViewExtensionsKt.isVisible(view)) {ViewExtensionsKt.setVisible(view, false);
}

至于怎么查看 Kotlin 转成的 Java 代码,方法如下:

  1. 在 Android Studio 顶部菜单中找到 「Tools → Kotlin → Show Kotlin Bytecode」
  2. 在右侧的 「Kotlin Bytecode」 窗口中点击 「Decompile」 按钮,就可以看到对应的 Java 代码了。

这里还有个小技巧,如果大家不喜欢 Kotlin 文件转成 Java 后默认的类的名字(例如上面的 ViewExtensionsKt),我们还可以自定义要转成 Java 的类名。

例如,在上例中的 ViewExtensions.kt 文件的顶部添加一行如下代码:

@file: JvmName("ViewUtils")

这样转成 Java 的类名就是 ViewUtils 了,如下:

public final class ViewUtils {public static final boolean isVisible(@NotNull View $this$isVisible) {Intrinsics.checkParameterIsNotNull($this$isVisible, "$this$isVisible");return $this$isVisible.getVisibility() == 0;}public static final void setVisible(@NotNull View $this$setVisible, boolean visible) {Intrinsics.checkParameterIsNotNull($this$setVisible, "$this$setVisible");$this$setVisible.setVisibility(visible ? 0 : 8);}
}

2. 扩展属性

Kotlin 除了可以扩展函数,还可以扩展属性。但是这个属性并不会保存在对象里,所以我们使用它时需要实现 「getter」 函数,如果是可变对象,则还要实现 「setter」 函数。格式如下:

val 类名.属性名: 类型get() {方法体}var 类名.属性名: 类型get() {方法体}set(value) {方法体}

下面,为视图扩展一个属性来判断其可见性:

val View.isVisible: Booleanget() {return visibility == View.VISIBLE}

在 Kotlin 中,当方法体内只有一条 return 语句时是可以简写的,如下:

val View.isVisible get() = visibility == View.VISIBLE

接着,将该属性改为 var,重写 「setter」 方法来设置可见性:

var View.isVisibleget() = visibility == View.VISIBLEset(value) {visibility = if (value) View.VISIBLE else View.GONE}

这样,在 Kotlin 中就可以这么使用了:

if (view.isVisible) {view.isVisible = false// ...
}

我们再来看看扩展属性的定义转成 Java 代码是什么样子的:

public final class ViewUtils {public static final boolean isVisible(@NotNull View $this$isVisible) {Intrinsics.checkParameterIsNotNull($this$isVisible, "$this$isVisible");return $this$isVisible.getVisibility() == 0;}public static final void setVisible(@NotNull View $this$isVisible, boolean value) {Intrinsics.checkParameterIsNotNull($this$isVisible, "$this$isVisible");$this$isVisible.setVisibility(value ? 0 : 8);}
}

大家可以看到,扩展属性和扩展方法转成的 Java 代码是一样的,因此在 Java 中使用的时候也是一样的。

最后再说个 dp 转 px 的例子,我们可以对 Number 类扩展一个属性,代码如下:

val Number.dp get() = round(toFloat() * Resources.getSystem().displayMetrics.density).toInt()

这样我们就可以直接使用 18.dp0.5.dp 这种形式将一个数字转成对应的 dp 大小,是不是很简洁?

3. Kotlin 扩展库

其实,Google 官方已经为我们扩展了很多实用的函数和属性,比如 https://developer.android.com/kotlin/ktx。

大家有兴趣的可以去引入一下慢慢探索~

参考

  • 《Kotlin 实战》

java属性定义_Kotlin 真香系列:扩展函数和属性相关推荐

  1. TypeScript真香系列-高级类型

    前言 TypeScript真香系列的内容将参考中文文档,但是文中的例子基本不会和文档中的例子重复,对于一些地方也会深入研究.另外,文中一些例子的结果都是在代码没有错误后编译为JavaScript得到的 ...

  2. 「真香系列」新物种首发亮相 聚划算爆款孵化玩法升级

    从普通商品到优质好物,差的便是那一句"真香". 2022聚划算99划算节,聚划算首发「真香系列」,为消费者精选了一批价格香.品质香.服务香的「十三香」好物.不过,聚划算的" ...

  3. android 小米相机问题吗,如果小米10把相机优化到位,那这款机器属于真香系列!...

    如果小米10把相机优化到位,那这款机器属于真香系列! 2020-05-12 22:42:42 32点赞 9收藏 15评论 今年小米10给人印象最深的是,它涨价了.发布会当时3999元起步就劝退了不少人 ...

  4. java实体字节属性定义_Java字节码方法表与属性表详解

    而这些字节其实对应的信息是它: 所以问题就来了,aload_0不是助记符信息么,怎么就能够跟字节码文件中的字节对应上呢?所谓助记符其实也就是帮忙我们去记忆的符合,在底层其实也是对应的一个个十六进制的数 ...

  5. Java——(1)定义一个学生类Student,包含属性:姓名(String name)、年龄(int age) (2)定义Map集合,用Student对象作为key

    分析以下需求,并用代码实现: (1)定义一个学生类Student,包含属性:姓名(String name).年龄(int age) (2)定义Map集合,用Student对象作为key,用字符串(此表 ...

  6. 真香系列之 Golang 升级

    Golang 以前的依赖管理一直饱受诟病,社区的方案也层出不穷,比如 vendor, glide, godep 等.之前的依赖管理一直是依靠 GOPATH 或者将依赖代码下载到本地,这种方式都有劣势. ...

  7. JVM真香系列:.java文件到.class文件

    认识JVM 什么是JVM JVM 全称 Java Virtual Machine,也就是我们耳熟能详的 Java 虚拟机.它能识别 .class后缀的文件,并且能够解析它的指令,最终调用操作系统上的函 ...

  8. 数据结构与算法邹永林PDF_真香系列:耗时大半个月收整全套「Java架构进阶pdf」没白费,终于可以安心备战2021了!...

    2021就这么来了,马上就要开启备战今年的"金三银四"了.辛亏在2020的最后半月花了我大半个月时间收整了全套的「Java架构进阶pdf」,这一波下来,刷完你就会知道,真真香啊,我 ...

  9. 真香系列!Java工程师面试该怎么准备

    前言 对Java开发的知识点进行深入的学习,并打算做成系列,先从基础常用的重点**(面试点)**知识开始,后续会陆续扩展,加油! 涉及到底层的可能代码块会多点,但要学习底层不看代码看啥?代码说明一切! ...

最新文章

  1. pageContext.findAttribute()与pageContext.getAttribute()的区别
  2. ksql中定义的本体在dataModel中不存在
  3. 文件服务器+好处,文件服务器 好处
  4. 【C语言入门教程】2.2 常量 与 变量
  5. bufg和bufgp_如何将自己写的verilog模块封装成IP核(一)
  6. Ecere SDK:用于GUI和图形的跨平台工具包
  7. 解释Linux进程的父子关系,Linux进程管理
  8. python super().__init__()_python——多继承使用super().__init__ 发生的状态
  9. BZOJ 2432 兔农
  10. css基础知识汇总8
  11. pandas 删除特定行根据条件_记录21个Pandas技巧
  12. 读书笔记(10)网络规划与设计
  13. 巧用京东物流分享链接批量查询多个京东快递的物流信息
  14. 【国家集训队】跳跳棋(LCA+二分答案)
  15. 逝去的岁月,回忆的青春
  16. Oracle存储过程
  17. 江西宜春三名公务员擅自驾公车钓鱼被通报-公车钓鱼-公务员-公车
  18. memcached(十三)注意事项
  19. 最新360安全卫士在线安装版
  20. 一键抠图:一款简单好用的图片处理软件(工具详资源)

热门文章

  1. 李航统计方法——感知机
  2. 大数据在智慧城市中重要的作用
  3. 物联网卡在建筑行业的应用结果
  4. Hive(二)——数据类型与文件格式
  5. python unicode编码转换中文_Python入门高级教程--Python 中文编码
  6. 基于深度学习的数字识别GUI的设计
  7. java哈密尔顿回路算法,用回溯方法求哈密尔顿回路——java求解
  8. 使用QEMU实现vexpress-ca9板卡的linux启动
  9. 真假签到题(签到+打表)
  10. mysql 端口 php_php - 如何修改mysql端口并对外开放。。