Kotlin-关于构造函数

421 阅读2分钟

整理一下kotlin的构造函数,有一些要注意的小细节。

1、主构造函数加或不加val/var有何区别?

例如下面这二个类:

class Person(val name: String?)
class Person2(name: String?)

反编译后的结果:

public final class Person {
   @Nullable
   private final String name;

   @Nullable
   public final String getName() {
      return this.name;
   }

   public Person(@Nullable String name) {
      this.name = name;
   }
}
public final class Person2 {
   public Person2(@Nullable String name) {
   }
}

添加了val/var会生成成员属性name,而如果不加则仅仅是一条构造函数。

val p = Person("")
val p2= Person2("")

另外需要注意的小细节:如果属性为val,则属性通过构造方法生成后不会再被修改。

2、主构造函数不能初始化的代码应该放在init代码块中,且主构造的参数可以在初始化块中使用。

class Person( val name: String?){
    init {
        print(name)
    }
}

另外多个init代码块和成员属性的初始化是按自上而下的顺序执行的。

3、次构造函数都要继承主构造函数,可以用@JvmOverloads简化。

比如:

class CustomView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
    View(context, attrs, defStyleAttr) {

    constructor(context: Context) : this(context, null)
    
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    
}

简化后:

class CustomView @JvmOverloads constructor (context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
    View(context, attrs, defStyleAttr) {
        
}

这时候代码会有警告提示给构造方法的参数提供默认值。

4、习惯了使用主次构造函数? 但有可能会带来问题。

当我们使用主构造函数的写法自定义WebView赋予默认值时:

class CustomWebView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : WebView(context, attrs, defStyleAttr) {

    init {
        //do something
    }
}

会发现自定义的WebView无法弹出软键盘了,这是因为defStyleAttr默认值给了0(具体原因这里不深究),我们可以将这个0修改为一条R.attr.webViewStyle属性或其他,也可以修改为非kotlin主构造函数的传统写法:

class CustomWebView : WebView {
    constructor(context: Context) : super(context)
    constructor(context: Context, @Nullable attrs: AttributeSet?) : super(context, attrs)
    constructor(
        context: Context,
        @Nullable attrs: AttributeSet?,
        defStyleAttr: Int
    ) : super(context, attrs, defStyleAttr)

    init {
        //do something
    }
}

个人学习笔记