【Android】Kotlin教程(4)

文章目录

1.field

field 关键字通常与属性的自定义 getter 和 setter 一起使用。当你需要为一个属性提供自定义的行为时,可以使用 field 来访问或设置该属性的实际存储值。

kotlin 复制代码
class Player {
    var age: Int = 0
        get() = field  // 自定义 getter
        set(value) {  // 自定义 setter
            if (value >= 0) {
                field = value
            } else {
                println("年龄不能为负数")
            }
        }
}

fun main() {
    val player = Player()

    player.age = 30  // 正常设置
    println(player.age)  // 输出 30

    player.age = -5  // 尝试设置无效的年龄
    println(player.age)  // 输出 30(因为设置失败,所以仍然是 30)
}

更复杂的自定义行为

kotlin 复制代码
class Person {
    private var _age: Int = 0  // 私有字段

    var age: Int
        get() {
            println("获取年龄: $_age")
            return _age
        }
        set(value) {
            if (value >= 0) {
                println("设置年龄: $value")
                _age = value
            } else {
                println("年龄不能为负数: $value")
            }
        }
}

fun main() {
    val person = Person()

    person.age = 30  // 输出: 设置年龄: 30
    println(person.age)  // 输出: 获取年龄: 30
                         //        30

    person.age = -5  // 输出: 年龄不能为负数: -5
    println(person.age)  // 输出: 获取年龄: 30
                         //        30
}
  • field 关键字:在自定义的 getter 和 setter 中,field 代表属性背后的实际存储字段。
  • 自定义 getter 和 setter:允许你在读取和写入属性时执行额外的逻辑,如数据验证、日志记录等。
  • 私有字段:为了更好地控制属性的访问,可以使用私有字段来存储实际值,并通过公开的属性提供访问接口。

2.计算属性

  • 计算属性:这些属性没有后台字段来存储值,而是通过 getter 方法在每次访问时计算并返回值。
  • 自定义 getter:你可以在类中定义一个没有显式初始化值的 val 属性,并为其提供一个自定义的 getter 方法。
kotlin 复制代码
class Rectangle(val width: Int, val height: Int) {
    // 计算属性
    val area: Int
        get() = width * height  // 自定义 getter
}

fun main() {
    val rectangle = Rectangle(10, 5)
    
    println("宽度: ${rectangle.width}")  // 输出 宽度: 10
    println("高度: ${rectangle.height}")  // 输出 高度: 5
    println("面积: ${rectangle.area}")  // 输出 面积: 50
}

3.主构造函数

在People类的定义头中定义一个主构造函数,使用临时变量为Player的各个属性提供初始值,在Kotlin中,为了便于识别临时变量通常都会以下划线开头的名字命名

kotlin 复制代码
class People(
    _name:String,
    _age:Int,
    _isNormal:Boolean
) {
    var name = _name
        get() = field.capitalize()
        set(value){
            field = value.trim()
        }
    var age = _age
        get() = field
        set(value){
            field = value.absoluteValue
        }
    var isNormal = _isNormal
}


fun main(){
    val people = People("Jack", 20, true)
    println(people.name)
    println(people.age)
    println(people.isNormal)
}

4.次构造函数

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

kotlin 复制代码
class People0(
    _name:String,
    var age:Int,
    var isNormal:Boolean
) {
    var name = _name
        get() = field.capitalize()
        set(value){
            field = value.trim()
        }

    constructor(name : String) : this(name , age = 10, isNormal = false) {
        this.name = name.capitalize()
    }

}


fun main(){


    val people0 = People0("rose")
    println(people0.name)  // Rose
    println(people0.age) // 0
    println(people0.isNormal) // false

}

5.默认参数

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

kotlin 复制代码
class People1(
    _name:String,
    var age:Int = 99,
    var isNormal:Boolean = false
) {
    var name = _name
        get() = field.capitalize()
        set(value){
            field = value.trim()
        }



    constructor(name : String) : this(name , age = 10, isNormal = false) {
        this.name = name.capitalize()
    }

}


fun main(){
    val people1 = People1(_name = "jim")
    println(people1.name) // Jim
    println(people1.age) // 99
    println(people1.isNormal) // false
}

6.初始化块

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

kotlin 复制代码
class People1(
    _name:String,
    var age:Int = 99,
    var isNormal:Boolean = false
) {
    var name = _name
        get() = field.capitalize()
        set(value){
            field = value.trim()
        }



    constructor(name : String) : this(name , age = 10, isNormal = false) {
        this.name = name.capitalize()
    }


    init {
        require(age > 0){"年龄设置不能小于0"}
    }
}


fun main(){
    val people1 = People1(_name = "jim",-1, false)
    println(people1.name) // Jim
    println(people1.age) // 198
    println(people1.isNormal) // false
}

7.初始化顺序

  • 主构造函数里声明的属性
  • 类级别的属性赋值
  • init初始化块里的属性赋值和函数调用
  • 次构造函数里的属性赋值和函数调用
kotlin 复制代码
class Student(
    _name : String,
    val age : Int
){
    var name = _name

    var score = 10

    var hobby = "music"

    val subject : String


    init {
        println("initializing student...")
        subject = "Chinese"
    }

    constructor(_name:String) : this(_name,10){
        score = 100
    }
}

fun main(){
    val student = Student("Jack")

}
kotlin 复制代码
   public Student(@NotNull String _name) {
      Intrinsics.checkNotNullParameter(_name, "_name");
      this(_name, 10);
      this.score = 100;
   }
   public Student(@NotNull String _name, int age) {
      Intrinsics.checkNotNullParameter(_name, "_name");
      super();
      this.age = age;
      this.name = _name;
      this.score = 10;
      this.hobby = "music";
      String var3 = "initializing student...";
      System.out.println(var3);
      this.subject = "Chinese";
   }

7.延迟初始化lateinit

  • 使用lateinit关键字相当于做了一个约定:在用它之前负责初始化
  • 只要无法确认lateinit变量是否完成初始化,可以执行isInitialized检查
kotlin 复制代码
class Player4 {
    lateinit var equipment : String

    fun ready(){
        equipment = "AK-47"
    }

    fun battle(){
        if (::equipment.isInitialized){
            println(equipment)
        }else{
            println("没有武器")
        }

    }
}

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

8.惰性初始化

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

kotlin 复制代码
class Player5(_name :String) {
    var name = _name

    val config by lazy {
        loadConfig()
    }

    private fun loadConfig():String{
        println("loading...")
        return "xxx"
    }
}


fun main() {
    val p = Player5("kim")
    Thread.sleep(4000)
    // 4s后才会打印
    println(p.config)
}
相关推荐
alexhilton1 小时前
Android的Agent优先时代:构建时vs运行时
android·kotlin·android jetpack
asdfg12589632 小时前
JavaBean是什么?怎么理解?有什么用途?
java·开发语言
Cutecat_2 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
dsyyyyy11012 小时前
JavaScript变量
开发语言·javascript·ecmascript
z落落3 小时前
C#WinForm 窗体切换与窗体传值(登录跳转案例)+WinForm 窗体传值(从上往下传、从下往上传)
开发语言·windows·c#
2601_961765293 小时前
【分享】PlayerPro媒体音乐播放器 完整专业版
android·媒体
allway23 小时前
How to Echo Multiline to a File in Bash [3 Methods]
开发语言·chrome·bash
weixin_462446233 小时前
手把手教你用 Bash 脚本自动更新 /etc/hosts —— 自动绑定网卡 IP 与节点名
开发语言·tcp/ip·bash
一个梦醒了3 小时前
安装git bash选项推荐
开发语言·git·bash
ct9783 小时前
React 状态管理方案深度对比
开发语言·前端·react