Kotlin学习-构造函数

Kotlin的构造函数分为主构造函数(primary constructor)和次级构造函数(secondary constructor);

主构造函数

1、在Kotlin中一个类可以有一个主构造函数和一个或多个次构造函数;如果不写构造函数会有一个默认空的构造函数

// 关键字 类名 类头(参数、主构造函数){ 类体 }
class MyTest{
}
var test =MyTest() //使用默认的构造函数创建对象

// 空的类
class MyTestEmpty
val empty = MyTestEmpty()

2、主构造函数是类头的一部分:它跟在类名(和可选的类型参数)后。如果主构造函数没有任何注解或可见性修饰符,constructor关键字可省略,否则是必须的;

// 主体构造器(primary constructor)
class MyTest constructor(name: String) {
}
// 省略了关键字的主体构造器( 没有注解和可见性修饰符就可以省略)
class MyTest1(name: String) {

}

3、主构函数不能包含任何代码,初始化代码放在以init关键字作为前缀的初始化块中;可以有多个init,也可以没有init,init的执行顺序是根据写的顺序来的

// 主体构造器的代码必须写在init(初始化)代码块里面
class MyTest(name: String) {
    val name: String
    init {
        this.name = name
        Log.d("MyTest","my name is ${this.name}")
    }
}

4、主构函数的参数可以在初始化块中使用,也可以在类体内声明的属性初始化器中使用;

5、与普通属性一样,主构函数中声明的属性也可以是可变(var )或者只读(val );

//2.类名MyTest后,主构造函数(name: String) ,无注解和可见性修饰符,constructor关键字省略
//5.主构函数中声明属性name是只读的
class MyTest(val name: String) {
  //3.主构函数无代码,放在init关键字初始化块中,
  private val name;
  init {
      Log.e("MyTest--","init1")
     this.name = name
  }
  init {
      Log.e("MyTest--","init2")
  }
  //4.主构函数参数可以类体内声明的属性初始化器中使用,或者初始化块中使用
  val testName = name.toUpperCase()
}
//此时constructor关键字不可省略
class MyTest private constructor(val name: String) { 
    private val name;
    init {
       this.name = name
    }
}

次构造函数

1、次构造函数声明必须有前缀constructor;而且是写在类体中

class MyTest {
    //1.次构造函数声明前缀有constructor
    constructor(name: String) {
       .....
    }
}

2、如果类有一个主构造函数,每个次构造函数可以使用this关键字,直接委托或者通过别的次构造函数间接委托给主构造函数;

class MyTest(var name: String) {
   var mName : String = name
   var mAge: Int = 0
   init {
        Log.e("MyTest--","init1")
        this.mName = name
        this.mAge = mAge

        Log.e("MyTest--","init mName = $mName mAge = ${mAge} name = ${name}")
    }
    //2.使用this关键字,直接委托给主构造函数
    constructor(name: String="1", age: Int): this(name){
        Log.e("MyTest--","construct 1")
        this.mName = name
        this.mAge =  age
        Log.e("MyTest--"," mName = $mName mAge = $mAge name = $name")
    }
}

3、如果一个抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造函数,可见性是public。如果不希望类有一个公有构造函数,需要声明一个带有非默认可见性的主构造函数;

//3.主动声明一个公有构造函数,“覆盖 ”没有声明任何主次构造函数默认生成的不带参数的主构造函数
class MyPrivateTest private constructor () {
}

特别注意点

1、当只写了主构造函数,没有次构造函数,就会覆盖了默认的空造函数,此时创建对象只能通过你写的主构造函数来调用
class MyTest(var name: String){
}
//调用
 var test1: MyTest = MyTest() // 这么调用默认的空的构造函数会报错
 val test2: MyTest = MyTest("name") //ok

或者如果按照下面的写法就可以调用了

class MyTest(){
}
//调用
 var test1: MyTest = MyTest() // ok
2、当只写了次构造函数,不写主构造函数,创建对象必须通过次构造函数调用,若不写空的参数构造函数,则调用空的构造函数会报错
open class MyTestTwo{
    constructor(){ // 1
        Log.e("MyTestTwo--", "MyTestTwo construct 1")
    }
    constructor(age: Int){ //2
        Log.e("MyTestTwo--", "MyTestTwo construct 2")
    }
    constructor(age: Int, name:String):this(age){ //3
        Log.e("MyTestTwo--", "MyTestTwo construct 3")
    }

//    var test1: MyTestTwo = MyTestTwo() // ok
//    val test2: MyTestTwo = MyTestTwo(2) //ok
//    val test3: MyTestTwo = MyTestTwo(2,"wf") //ok
}
//如不写1的空构造函数, 则test1的初始化就会报错
3、当写了既写了主构造,又写了次构造函数,可以直接调用主构造函数或者调用次构造函数创建对象。次构造函数最终都是调用主构造函数来创建对象的。

比如:下面的 constructor(age:int):this("test")是直接代理主构造函数, 而间接的constructor,比如:constructor(age: Int, name:String):this(age)这个就代理了的次constructor,而上面次constructor又代理了主构造函数。而且调用的顺序是从先执行this再执行调用的构造函数,创建对象的调用顺序先调用的主构造函数->直接代理主函数的构造函数->间接代理主函数的构造函数->我们调用的构造函数。

open class MyTestOne(var name: String){
    init {
        Log.e("MyTestOne--", "MyTestOne init")
    }
    constructor(age: Int):this("test"){
        Log.e("MyTestOne--", "MyTestOne construct 1")
    }
    constructor(age: Int, name:String):this(age){
        Log.e("MyTestOne--", "MyTestOne construct 2 $name")
    }

//    val test1: MyTestOne = MyTestOne("name") //ok
//    val test2: MyTestOne = MyTestOne(1)  //ok
//    val test3: MyTestOne = MyTestOne(1,"wf") //ok
}

参考文章:
Kotlin学习系列之:Kotlin的构造函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容