美文网首页
Kotlin-构造函数

Kotlin-构造函数

作者: 杨0612 | 来源:发表于2021-03-01 16:12 被阅读0次
    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,定义主构造函数,把入参当作属性,让代码更简洁;

    以上分析有不对的地方,请指出,互相学习,谢谢哦!

    相关文章

      网友评论

          本文标题:Kotlin-构造函数

          本文链接:https://www.haomeiwen.com/subject/hykvfltx.html