(十四)Kotlin简单易学 基础语法-类定义

(十四)Kotlin简单易学 基础语法-类定义,第1张

(十四)Kotlin简单易学 基础语法-类定义

field

针对你定义的每一个属性,Kotlin都会产生一个field,一个getter,以及一个setter,field用来存储属性数据,你不能直接定义field,Kottlin会封装field,保护它里面的数据,只暴露给getter和setter使用。属性的getter方法决定你如何读取属性值,每个属性都有getter方法,setter方法决定你如何给属性赋值,所以只有可变属性才会有setter方法,尽管Kotlin会自动提供默认的getter和setter方法,但在需要控制如何读写属性数据时,你也可以自定义他们。


class Player {
    var name: String = "jack"
        get() = field.capitalize()
        //重新赋值
        set(value){field = value.trim()}
}

fun main() {
    var p = Player()
    p.name = "rose"
    print(p.name)
}

计算属性

计算属性是通过一个覆盖的get或set运算符来定义,这是field就不需要了。

class Player {
    val rolledValue 
    //通过一个覆盖的get或set运算符来定义
        get() = (1..6).shuffled().first()
}

fun main() {
    var p = Player()
    print(p.rolledValue)
}

防范竞态条件

如果一个类属性即可空又可变,那么引用它之前必须保证它非空,一个办法是用also标准函数。

class AlsoTest {

    var words:String?="hello"

    fun saySomething(){
        words?.also {
            print("Hello ${it.toUpperCase()}")
        }
    }
}

fun main() {
    val alsoTest = AlsoTest()
    print(alsoTest.saySomething())
}

主构造函数

我们在Play类的定义头中定义一个主构造函数,使用临时变量为Player的各个属性提供初始值,在Kotlin中,为便于识别,临时变量(包括仅引用一次的参数),通常都会以下划线开头的名字命名。


//创建构造函数
class P(_name: String, _age: Int, _isNormal: Boolean) {
    var name = _name
    var age = _age
    var isNormal = _isNormal
}

fun main() {
    val p = P("Javk", 18, false)
    //输出Javk
    print(p.name)
}

在主构造函数里定义属性

Kotlin允许你不使用临时变量赋值,而是直接用一个定义同时指定参数和类属性,通常我们更喜欢用这个方式定义类属性,因为它会减少重复代码。

class P(_name: String, var _age: Int, var _isNormal: Boolean) {
    var name = _name
}

fun main() {
    val p = P("Javk", 18, false)
    print(p.name)
}

次构造函数

有主就有次,对应主构造函数的次构造函数,我们可以定义多个次构造函数来配置不同的参数组合。


class P(var _name: String, var _age: Int, var _isNormal: Boolean) {
		//次构造函数
    constructor(name: String) : this(name, _age = 10, _isNormal = false)

}

fun main() {
    val p = P("Rose")
    //输出Rose
    print(p._name)
}

使用次构造函数

使用次构造函数,定义初始化代码逻辑。


class P(var _name: String, var _age: Int, var _isNormal: Boolean) {

    constructor(name: String) : this(name, _age = 10, _isNormal = false)
//    使用次构造函数,定义初始化代码逻辑。
    constructor(name:String,age:Int) :this(name,age,_isNormal = false){
        this._name =name.toUpperCase()
    }
}

fun main() {
    val p = P("Rose")
    //输出Rose
    print(p._name)

    val p3 = P("aose",20)
    // AOSE
    print(p3._name)
}

默认参数

定义构造函数时,可以给构造函数参数指定默认值,如果用户调用时不提供值参,就使用这个默认值。

class T (var _name:String, var _age:Int = 20){
}

fun main() {
//    val t =T("Jac")
    val t = T(_name = "jack");
    //输出20
    print(t._age)
}

初始化块

初始化可以设置变量或值,以及执行有效性检查,如检查传给某构造函数的值是否有效,初始化块代码会在构造类实例时执行。

class T (var _name:String, var _age:Int = 20){

    //构建对象时,调用init函数
    init {
        require(_age>0){"age muse be positive"}
        require(_name.isNotBlank()){"palyer must have a name."}
    }
}

fun main() {
//    val t =T("Jac")
    val t = T(_name = "");
    //输出20
    print(t._age)
  
 // 抛出异常
  Exception in thread "main" java.lang.IllegalArgumentException: palyer must have a name.
	at kotlin0.T.<init>(T.kt:8)
	at kotlin0.T.<init>(T.kt:3)
	at kotlin0.TKt.main(T.kt:14)
	at kotlin0.TKt.main(T.kt)

Process finished with exit code 1

}

初始化顺序

➢主构造函数里声明的属性
➢ 类级别的属性赋值
➢ init初始化块里的属性赋值和函数调用
➢次构造函数里的属性赋值和函数调用

// 第一步执行 var age:Int
class Sudent(_name:String ,var age:Int) {
	// 第二 类级别的属性赋值
    var  name = _name
    var score = 10
    private val hobby = "music"
    val  subject:String
    
    //第三部init初始化块
    init {
        print("initializing" +
                " student")

        subject = "math"

    }
	//第四部 次构造函数里的属性赋值和函数调用
    constructor(_name: String):this(_name,10){
        score =20
    }
}

fun main() {
    Sudent("jack")
}


lateinit 延迟初始化

➢使用lateinit关键字相当于做了一个决定:在用它之前负责初始化
➢只要无法确认lateinit变量是否完成初始化,可以执行isInitialized检查



class Player4 {
    //lateinit关键字相当于做了一个决定:在用它之前负责初始化
    lateinit var equipment:String

    fun  ready(){
        equipment = "Ak47"
    }
    fun battle(){
        //只要无法确认lateinit变量是否完成初始化,可以执行isInitialized检查
        if (::equipment.isInitialized)
        print(equipment)
    }
}

fun main() {
    val p = Player4()
//    p.ready()
    p.battle()
}

by lazy 惰性初始化

➢延迟初始化并不是推后初始化的唯一方式,你也可以暂时不初始化某个变量,直到首次使用它,这个叫做惰性初始化。

class Player5(_name:String) {
var  name = _name
    //延迟初始化并不是推后初始化的唯一方式,你也可以暂时不初始化某个变量,
    // 直到首次使用它,这个叫做惰性初始化。
    val cofig by lazy { loadCongig()}

    private fun  loadCongig():String{
        return "xxxx"
    }

}

fun main() {
    val player5 = Player5("jackal")
    Thread.sleep(3000)
    //三秒后输出xxxx
    print(player5.cofig)
}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/918700.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-16
下一篇2022-05-16

发表评论

登录后才能评论

评论列表(0条)

    保存