kotlin构造函数默认值编译器是如何处理的?

当我们给构造函数指定了默认值,并且存在重载的构造函数,

比如如下场景

class Foo(val a: String, val b: Boolean = false) {
}

// 调用Foo("hello") 此时b是true
// 修改Foo类定义
class Foo(val a: String, val b: Boolean = false) {
   constructor(a: String): this(a, false) {}
}
// 此时调用Foo("hello") 此时b是false

如上代码场景,kotlin是如何决定在重载的时候调用哪一个构造函数呢?

首先kotlin是如何处理含有默认值的函数的编译的?

kotlin会往原始函数后追加两个参数,一个是mask,一个是DefaultConstructorMarker,mask的作用用来告知哪一些默认参数是显示传递的,哪一些默认参数是使用默认值的,DefaultConstructorMarker是为了避免构造函数冲突,假设我有另外一个构造函数参数相同,末尾也是int,不加标记区分,无法区分这两个构造函数,实际调用过程中,这个构造函数始终为空。

举个例子,以上图中的Foo为例子

class Foo(val a: String, val b: Boolean = false) {
}

这个构造函数经过kotlin编译器处理后会变成

class Foo {
   public Foo(@NotNull String a, boolean b) {
      Intrinsics.checkNotNullParameter(a, "a");
      super();
      this.a = a;
      this.b = b;
   }
   
   public Foo(String var1, boolean var2, int var3, DefaultConstructorMarker var4) {
      if ((var3 & 2) != 0) {
         var2 = false;
      }

      this(var1, var2);
   }
}

会生成两个函数,一个函数是两个值都指定的,还有一个函数是会使用默认值的。

重载决议: 选择最具体最合适的函数

如何定义最具体:kotlin的标准是如果一个构造函数使用的默认值更少,那么这个构造函数更具体,

回到上文的例子,

  1. 对比调用点和对应的构造函数,如上例子,如果选择Foo(val a: String, val b: Boolean = false) ,那么有1个参数使用默认值,如果选择constructor(a: String),针对构造函数参数来说,这个构造函数不需要使用默认值。因此最终构造函数决议会使用这个构造函数。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容