Kotlin基础语法 七、类与构造函数

一、类的声明

和Java一样,Kotlin 中使用关键字 class 声明类。
类声明由可见性修饰符、类名、类头(指定其类型参数、主构造函数等)以及由花括号包围的类体构成。类头与类体都是可选的; 如果一个类没有类体,可以省略花括号。
一个相对完整的类声明格式如下:
可见性修饰符 class 类名 constructor(参数列表){
类体
}
类的可见性修饰符默认为public,可省略
具体示例看构造函数部分

二、类的构造函数

解析:

  1. 在Kotlin中,允许有一个主构造函数和多个次构造函数(也叫辅助构造函数、二级构造函数)。其中主构造函数是类头的一部分,它跟在类名后面。次构造函数声明在函数体中。 主构造函数和次构造函数的区别我们可以理解为Java中声明多个参数不同的构造函数。
  2. 主构造函数和次构造函数都使用关键字constructor声明,如果主构造函数没有任何注解或者可见性修饰符,可以省略 constructor 关键字。次构造函数不能省略constructor 关键字

构造函数具体定义如下:

2.1、)主构造函数
主构造函数是类头的一部分,类名的后面跟上构造函数的关键字constructor以及类型参数。

示例:

class Person constructor(val userName : String , val userAge : Int) {
    
}

当是默认的可见性修饰符且不存在任何注解 ,主构造函数constructor关键字可以省略。如下:

class Person(val userName : String , val userAge : Int) {
    
}

当主构造函数不是默认可见性修饰符或者存在注解,不能省略constructor关键字
如下:

class Person private constructor(val userName : String , val userAge : Int) {

}
class Person @Inject constructor(val userName : String , val userAge : Int) {

}
class Person private @Inject constructor(val userName : String , val userAge : Int) {

}

2.2 、)构造函数的初始化代码块

  1. 主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。
  2. 可以有多个初始化代码块,在实例对象初始化期间,初始化代码块按照它们出现在类体中的顺序执行,与属性初始化器交织在一起。
  3. 主构造的参数可以在初始化块中使用。也可以在类体内声明的属性初始化器中使用。
  4. 可以在构造函数中声明类的属性,要求参数列表中的参数添加val或var前缀,这将简化代码量
    如下:
class Person constructor(val userName : String , val userAge : Int) {}
上面的代码等价于
class Person constructor(userName : String , userAge : Int) {
    var userName : String
    var userAge : Int
    init {
        this.userName = userName
        this.userAge = userAge
    }
}

一个完整的类构造函数及初始化示例:

class Person constructor(val userName : String , val userAge : Int) {

    val userHello = "hello! $userName"

    init {
        Log.e("初始化代码块1初始化了" , "userName:$userName,userAge:$userAge")
      //  userHello //可以正常调用
        //userName2 //报错,userName2必须先初始化
    }

    val userName2 = "用户的名字:${userName}"
    val userAge2 = "用户的年龄:${userAge}"

    init {
        Log.e("初始化代码块2初始化了" , "$userName2,$userAge2")
    }

}
val person = Person("jf" , 26)

上述代码的运行结果:
初始化代码块1初始化了: userName:jf,userAge:26
初始化代码块2初始化了: 用户的名字:jf,用户的年龄:26
可以看到 初始化代码块和属性是按照我们代码顺序进行初始化的。

2.3、)次构造函数
可以在类体中声明前缀有 constructor的次构造函数

  1. 次构造函数 constructor 关键字不能省略。可见性修饰符也默认为public

  2. 次构造函数没有初始化代码块,但可以有方法体进行初始化

  3. ) 同时存在主构造函数和二级构造函数时的情况
    如果类具有主构造函数,则每个辅助构造函数需要通过另一个辅助构造函数直接或间接地委派给主构造函数。 使用this关键字对同一类的另一个构造函数进行委派。
    想一想Java 中不同参数的多个构造函数之间相互调用初始化的情形,这是非常好理解的,可以继续看4.)的解释。
    如下:

class Person constructor(val userName : String , val userAge : Int) {
    constructor(userAge : Int) : this("暂无姓名" , userAge)
}
  1. )初始化块中的代码实际上会成为主构造函数的一部分。委托给主构造函数会作为次构造函数的第一条语句,因此所有初始化块与属性初始化器中的代码都会在次构造函数体之前执行。即使该类没有主构造函数,这种委托仍会隐式发生,并且仍会执行初始化块

示例如下:

class Person constructor(val userName : String , val userAge : Int) {

    init {
        Log.e("初始化代码块1初始化了" , "userName:$userName,userAge:$userAge")
    }

    val userName2 = "用户的名字:${userName}"
    val userAge2 = "用户的年龄:${userAge}"

    init {
        Log.e("初始化代码块2初始化了" , "$userName2,$userAge2")
    }

    constructor(userAge : Int) : this("暂无姓名" , userAge) {
        Log.e("次构造函数代码体调用了" , "-----------")
    }
}
val person = Person( 26)

上述代码的运行结果如下:
初始化代码块1初始化了: userName:暂无姓名,userAge:26
初始化代码块2初始化了: 用户的名字:暂无姓名,用户的年龄:26
次构造函数代码体调用了: -----------
很明显,次级构造函数在运行自己的方法体之前先完成了主构造函数的初始化过程。

  1. 如果一个非抽象类没有声明任何(主或次)构造函数,它会有一个生成的不带参数的主构造函数。构造函数的可见性是 public。如果你不希望你的类有一个公有构造函数,你需要声明一个带有非默认可见性的空的主构造函数:
class Person public constructor(){
    
}
等同于
class Person (){

}
等同于
class Person{

}

进行私有主构造函数
class Person private constructor(){
    
}
  1. 使用构造函数声明属性,也可以使用默认参数。如果我们不传入参数则使用默认参数
class Person constructor(val userName : String = "默认用户" , val userAge : Int = 18) {}
val person = Person() // 我们不传入参数则使用默认参数

三、创建类的实例

要创建一个类的实例,我们就像普通函数一样调用构造函数:注意 Kotlin 并没有 new 关键字。
val person = Person()

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值