整理一下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
}
}