Kotlin-构造函数
2021-03-01 本文已影响0人
杨0612
1.Kotlin与Java构造函数常规写法对比,以自定义View为例
不同点:
1.1 Kotlin以constructor命名构造函数,Java以类名命名构造函数;
1.2 Kotlin构造可以没有方法体(花括号),Java必须得有(花括号);
1.3 Kotlin init代码块可以做常规初始化处理,Java需要自定义类似init方法并主动调用;
相同点:
1.4 两者super跟this代表的意思都是一样;
//Kotlin写法
class MyViewKotlin : View {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(
context,
attrs,
defStyleAttr,
defStyleRes
)
init {
//do something
}
}
//Java写法
public class MyViewJava extends View {
public MyViewJava(Context context) {
super(context);
init();
}
public MyViewJava(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public MyViewJava(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public MyViewJava(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
//do something
}
}
2.Kotlin的优化
一定有人觉得上述Java或Kotlin的写法过于繁琐,虽然AS可以自动生成,但是代码看起来就很冗余,接下来看下Kotlin是怎么玩的。定义一个构造函数,给参数设置默认值,这样就相当于重载了多个构造函数可以满足不同场景。
class MyViewKotlin : View {
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : super(
context,
attrs,
defStyleAttr,
defStyleRes
)
init {
//do something
}
}
//调用一个参数的
MyViewKotlin(this)
//调用两个参数的
MyViewKotlin(this, null)
//调用三个参数的
MyViewKotlin(this,null,0)
//调用四个参数的
MyViewKotlin(this,null,0,0)
3.Kotlin的默认构造函数、主构造函数、次构造函数
默认构造函数:如果没有自定义任何构造函数,那么就会有一个默认无参的构造函数可以调用,这点跟Java一样;
主构造函数:定义在类名后面的构造函数就是主构造函数,个数<=1;
次构造函数:定义在类体内的构造函数都是次构造函数,个数 >=0;
//案例1,没有主构造函数,只有一个默认的无参构造函数
class Test1 {}
//案例2,有一个主构造函数,默认的无参构造函数无法使用
class Test2 constructor(name: String) {
var name: String = name
}
//案例3,只有一个主构造函数,如果构造函数没有任何修改符(例如private)或注解,那么constructor关键字可以省略
class Test3(name: String) {
var name: String = name
}
//案例4,有一个主构造函数和一个次构造函数
class Test4(name: String) {
var nameT: String = name
var ageT: Int? = null
constructor(name: String, age: Int) : this(name) {
ageT = age
}
}
//案例5,只有一个次构造函数
class Test5 {
var nameT: String? = null
var ageT: Int? = null
constructor(name: String, age: Int) {
nameT = name
ageT = age
}
}
4.Kotlin主、次构造函数的区别
主构造函数定义在类名后,没有方法体,对于属性的赋值直接跟在属性定义后面,使代码更简洁;
次构造函数定义在类体内,有方法体,对于属性的赋值是在函数内,这跟Java类似;
class Test6 constructor(name: String, age: Int) {
//主构造函数的属性赋值,也可以通过init代码块赋值
var nameT: String = name
var ageT: Int? = age
var sexT: Int? = null
constructor(name: String, age: Int, sex: Int) : this(name, age) {
//次构造函数的赋值
sexT = sex
}
}
5.Kotlin构造函数的特点
5.1如果定义了主构造函数,那么在init代码块中可以调用主构造函数的入参,因为init属于构造的一部分,而成员方法test就不行;
class Test7 constructor(name: String, age: Int) {
init {
//可以调用入参变量
Log.i("Test7", "name=${name} age=${age}")
}
private fun test() {
//无法调用入参变量
Log.i("Test7", "name=${name} age=${age}")
}
}
5.2 次构造函数后面是调用this还是super,完全取决于该构造函数的功能,没有固定,但如果定义了主构造函数,那么次构造函数必须间接或者直接调用主构造函数;
open class Test8Parent {
var nameT: String? = null
constructor(name: String) {
nameT = name
}
}
//继承Test8Parent
class Test8 : Test8Parent {
var ageT: Int? = 0
var sexT: Int? = 0
//冒号后面是调用this还是super,完全取决于该构造函数的功能,没有固定
constructor(name: String, age: Int) : this(name, 0, 0) {
ageT = age
}
//冒号后面是调用this还是super,完全取决于该构造函数的功能,没有固定
constructor(name: String, age: Int, sex: Int) : super(name) {
sexT = sex
}
}
5.2 如果父类有主构造函数,子类也必须得有,否则提示"Supertype initialization is impossible without primary constructor"
open class Test9Parent(name: String) {
var nameT: String? = name
}
//继承Test9Parent
class Test9(name: String, age: Int, sex: Int) : Test9Parent(name) {
var ageT: Int? = age
var sexT: Int? = sex
}
5.3 如果定义了主构造函数,可以把入参当作属性,省去定义;
class Test10 constructor(name: String, age: Int) {
//常规定义属性的办法
var nameT: String? = name
var ageT: Int? = age
private fun test() {
Log.i("Test7", "name=${nameT} age=${ageT}")
}
}
//把入参当作属性
class Test11 constructor(var nameT: String, var ageT: Int) {
private fun test() {
Log.i("Test7", "name=${nameT} age=${ageT}")
}
}
6.总结
6.1Kotlin,利用主构造函数以及设置默认值,可以让构造函数更简洁;
6.2Kotlin,定义主构造函数,可以在定义属性的时候就赋值;
6.3Kotlin,定义主构造函数,把入参当作属性,让代码更简洁;
以上分析有不对的地方,请指出,互相学习,谢谢哦!