一篇文章弄懂kotlin的扩展方法

作者:DROID 时间:2022-06-05 08:06:20 

Usage

扩展函数是 kotlin 的又一杀手锏功能,能够在不修改源码的基础上,扩展某些类的能力,方便开发。

例如这里演示了给 String 添加一个获取第一个元素的方法。


fun String.first(): Char {
 if (isEmpty()) {
   throw NoSuchElementException("String is empty")
 }
 return this[0]
}

fun main(args: Array<String>) {
 println("Hello,World".first())
}

这里需要额外注意的地方在于扩展函数的方法体中,是能够直接访问扩展对象 public 的变量的。例如上面的方法里面,我们也可以这么写:


fun String.first(): Char {
 if (length < 1) {
   throw NoSuchElementException("String is empty")
 }
 return this[0]
}

通过 this 可以在方法内,访问扩展对象,这里就是通过 this[0] 拿到第一个字符的。

Under in hood

看上去很厉害哈,但他的原理却非常简单。我们要时刻记住,kotlin JVM 是基于 JVM 开发的,kotlin 源码最后会变成字节码而后被运行。当遇到语法上不太懂的地方,直接反编译字节码,或者 Decompile 成 Java 方法,就能洞察里面的玄机。

我们将上述代码,Decompile 成 Java 后,就能发现里面的秘密。


public static final char first(@NotNull String $this$first){
 Intrinsics.checkParameterIsNotNull($this$first, "$this$first");
 if ($this$first.length() < 1) {
  throw (Throwable)(new NoSuchElementException("String is empty"));
 } else {
  return $this$first.charAt(0);
 }
}

原来是生成了一个 public static final 的方法呀,不过这个生成是 kotlin 提供的语法糖,帮我们完成的。看到这个代码,也解释了为什么在扩展对象方法内部,能够访问到扩展对象的 public 成员。

重载与多态

扩展方法能否被继承呢,或者重载呢?我们来看看例子


open class Animal
class Dog : Animal()

fun Animal.desc() = "Animal"
fun Dog.desc() = "Dog"

fun main(args: Array<String>) {
 println(Dog().desc())
 var animal: Animal = Dog()
 println(animal.desc())
}

// output:
// Dog
// Animal

如果扩展方法能够被重载,那么两次都应该输出 Dog,我们还是和前面方法一样,来看看真相。


@NotNull
public static final String desc(@NotNull Animal $this$desc) {
 Intrinsics.checkParameterIsNotNull($this$desc, "$this$desc");
 return "Animal";
}

@NotNull
public static final String desc(@NotNull Dog $this$desc) {
 Intrinsics.checkParameterIsNotNull($this$desc, "$this$desc");
 return "Dog";
}

可以看到实际生成了两个 desc 方法,里面的参数不动,所以这个方法的调用,只与扩展对象本身有关系,在编译时已经确定,不存在多态。

扩展属性

这是一个很神奇的设定,kotlin 并不能真的给扩展对象添加一个属性,而只是提供了一个语法糖,什么意思呢?我们具体看看下面这个例子。


var String.first: Char
 get() {
   if (isEmpty()) {
     throw NoSuchElementException(“String is empty”)
   }
   return this[0]
 }
 set(value) {
   println(“set value to $value”)
 }

fun main() {
 “Hello, World”.first = ‘G'
 println(“Hello,World”.first)
}

我们扩展了 kotlin 的属性,添加了一个 first。我们可以分别给这个所谓的 first 属性,注意是所谓的,添加 get 和 set 方法。然后我们可以通过 = 和 . 来调用 set 和 get 方法,就像 main 方法中那样。但实际上,最后并没有生成 first 属性,我们来看看反编译过后的代码。


public static final Char getFirst(@NotNull String $this$first) {
 Intrinsics.checkParameterIsNotNull($this$first, "$this$first");
 CharSequence var1 = (CharSequence)$this$first;
 boolean var2 = false;
 if (var1.length() == 0) {
  throw (Throwable)(new NoSuchElementException("String is empty"));
 } else {
  return $this$first.charAt(0);
 }
}

public static final void setFirst(@NotNull String $this$first, char value) {
 Intrinsics.checkParameterIsNotNull($this$first, "$this$first");
 String var2 = "set value to " + value;
 boolean var3 = false;
 System.out.println(var2);
}

看到没有,实际上只是添加了 setFirst 和 getFirst 两个方法,并没有实际的属性添加上去。这也是 kotlin 提供给我们的语法糖之一,糖要吃,但也要小心蛀牙哦!

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

来源:https://woaitqs.cc/2019/09/08/kotlin-extension-method/

标签:kotlin,扩展,方法
0
投稿

猜你喜欢

  • c# 利用易福门振动模块VSE002采集振动数据的方法

    2022-10-13 00:12:25
  • Java利用MultipartFile实现上传多份文件的代码

    2023-11-25 11:29:13
  • 详解Spring Boot自动装配的方法步骤

    2023-11-18 15:02:18
  • java学生管理系统界面简单实现(全)

    2023-11-28 21:35:25
  • Springboot与Maven多环境配置的解决方案

    2023-11-29 08:53:58
  • 将本地的jar包打到Maven的仓库中实例

    2022-08-29 13:38:28
  • MyBatis 如何获取子类的属性

    2022-09-12 14:42:39
  • Java递归寻路实现,你真的理解了吗

    2022-09-17 02:24:34
  • mybatis多表查询的实现(xml方式)

    2021-07-11 01:21:38
  • 关于@Scheduled不执行的原因分析

    2021-06-27 17:13:20
  • 深入探究Java线程的创建与构造方法

    2023-05-29 22:02:45
  • SpringBoot整合MongoDB的步骤详解

    2023-10-11 17:20:32
  • java加载properties文件的六种方法总结

    2023-09-20 05:24:54
  • C#.net实现在Winform中从internet下载文件的方法

    2023-09-13 18:04:15
  • 200行java代码实现2048小游戏

    2023-11-29 12:03:57
  • Java内存模型中的虚拟机栈原理分析

    2022-02-08 04:41:33
  • SpringBoot JS-SDK自定义微信分享的实现

    2023-11-10 05:08:28
  • java9开始——接口中可以定义private私有方法

    2023-03-27 06:53:15
  • 将Java的List结构通过GSON库转换为JSON的方法示例

    2023-02-13 20:33:52
  • Java解析调用webservice服务的返回XML串详解

    2023-11-07 02:42:01
  • asp之家 软件编程 m.aspxhome.com