Kotlin基础语法五

  • 继承与重载的open关键字

    KT所有的类,默认是final修饰的,不能被继承,和Java相反

    open:移除final修饰

  • 类型转换

    open class Person2(private val name: String) {

    复制代码
      fun showName() = "父类 的姓名是【$name】"
    
      // KT所有的函数,默认是final修饰的,不能被重写,和Java相反
      open fun myPrintln() = println(showName())

    }

    class Student2(private val subName: String) : Person2(subName) {

    复制代码
      fun showName2() = "子类 的姓名是【${subName}】"
    
      override fun myPrintln() = println(showName2())

    }

    // TODO 84.Kotlin语言的类型转换学习
    // 1.普通运行子类输出
    // 2.is Person Student File
    // 3.is + as 转换
    fun main() {
    val p: Person2 = Student2("王五")
    p.myPrintln()

    复制代码
      println(p is Person2)
      println(p is Student2)
      println(p is File)
    
      // is + as = 一般是配合一起使用
      if (p is Student2) {
          (p as Student2).myPrintln()
      }
    
      if (p is Person2) {
          // (p as Person2).myPrintln() // 因为子类重写了父类
          println((p as Person2).showName())
      }

    }

  • 智能类型转换

    open class Person3(val name: String) {
    private fun showName() = "父类显示:$name"

    复制代码
      open fun myPrintln() = println(showName())
    
      fun methodPerson() = println("我是父类的方法...") // 父类独有的函数

    }

    class Student3(val nameSub: String) : Person3 (nameSub) {
    override fun myPrintln() = println("子类显示:$nameSub")

    复制代码
      fun methodStudent() = println("我是子类的方法...") // 子类独有的函数

    }

    fun main() {
    val p : Person3 = Student3("李四")

    复制代码
      (p as Student3).methodStudent()
    
      p.methodStudent()
      // 智能类型转换:会根据上面 as 转成的类型,自动明白,你现在的类型就是上面的类型

    }

  • Any超类

    所有的类都默认继承Any超类,等于Java的Object

  • 对象声明 object

  • 对象表达式

    interface RunnableKT {
    fun run()
    }

    open class KtBase88 {
    open fun add(info: String) = println("KtBase88 add:info") open fun del(info: String) = println("KtBase88 del:info")
    }

    // 1.add del println
    // 2.匿名对象表达式方式
    // 3.具名实现方式
    // 4.对Java的接口 用对象表达式方式
    fun main() {
    // 匿名对象 表达式方式
    val p : KtBase88 = object : KtBase88() {

    复制代码
          override fun add(info: String) {
              // super.add(info)
              println("我是匿名对象 add:$info")
          }
    
          override fun del(info: String) {
              // super.del(info)
              println("我是匿名对象 del:$info")
          }
      }
      p.add("李元霸")
      p.del("李连杰")
    
      // 具名实现方式
      val p2 = KtBase88Impl()
      p2.add("刘一")
      p2.del("刘二")
    
      // 对Java的接口 用   KT[对象表达式方式]  方式一
      val p3 = object : Runnable {
          override fun run() {
              println("Runnable run ...")
          }
      }
      p3.run()
    
      // 对Java的接口 用   Java最简洁的方式 方式二
      val p4 = Runnable {
          println("Runnable run2 ...")
      }
      p4.run()
    
      // 对KT的接口 用   KT[对象表达式方式]  方式一
      object : RunnableKT {
          override fun run() {
              println("RunnableKT 方式一 run ...")
          }
      }.run()
    
      // 对KT的接口 用   Java最简洁的方式 方式二
      /*RunnableKT {
    
      }*/

    }

    // 小结:Java接口,有两种方式 1(object : 对象表达式) 2简洁版,
    // KT接口,只有一种方式 1(object : 对象表达式)

    // 具名实现 具体名字 == KtBase88Impl
    class KtBase88Impl : KtBase88() {

    复制代码
      override fun add(info: String) {
          // super.add(info)
          println("我是具名对象 add:$info")
      }
    
      override fun del(info: String) {
          // super.del(info)
          println("我是具名对象 del:$info")
      }

    }

  • 伴生对象

    // 伴生对象的由来: 在KT中是没有Java的这种static静态,伴生很大程度上和Java的这种static静态 差不多的
    // 无论 KtBase89() 构建对象多少次,我们的伴生对象,只有一次加载
    // 无论 KtBase89.showInfo() 调用多少次,我们的伴生对象,只有一次加载
    // 伴生对象只会初始化一次

    复制代码
      companion object {
          val info = "UserInfo"
          fun showInfo() = println("显示:$info")
          val name = "Derry"
      }
  • 内部类 & 嵌套类

    // TODO 内部类
    // 内部类的特点: 内部的类 能访问 外部的类
    // 外部的类 能访问 内部的类
    class Body(_bodyInfo: String) { // 身体类

    复制代码
      val bodyInfo = _bodyInfo
    
      fun show() {
          Heart().run()
      }
    
      // 默认情况下:内部的类 不能访问 外部的类,要增加修饰符inner 成为内部类才可以访问外部类
      inner class Heart { // 心脏类
          fun run() = println("心脏访问身体信息:$bodyInfo")
      }
    
      inner class Kidney { // 肾脏
          fun work() = println("肾脏访问身体信息:$bodyInfo")
      }
    
      inner class Hand { // 手
          inner class LeftHand { // 左手
              fun run() = println("左手访问身体信息:$bodyInfo")
          }
    
          inner class RightHand { // 右手
              fun run() = println("右手访问身体信息:$bodyInfo")
          }
      }

    }

    // 默认情况下:就是嵌套类关系
    // 嵌套类特点:外部的类 能访问 内部的嵌套类
    // 内部的类 不能访问 外部类的成员
    class Outer {
    val info: String = "OK"
    fun show() {
    Nested().output()
    }

    复制代码
      class Nested {
          fun output() = println("嵌套类")
      }

    }

    fun main() {
    // 内部类:
    Body("isOK").Heart().run()
    Body("isOK").Hand().LeftHand().run()
    Body("isOK").Hand().RightHand().run()

    复制代码
      // 嵌套类:
      Outer.Nested().output()

    }

  • 数据类

    // set get 构造函数 解构操作 copy toString hashCode equals 数据类 生成 更丰富
    data class ResponseResultBean2(var msg: String, var code: Int, var data: String) : Any()

  • copy

    // 深拷贝 重新创建对象
    data class User(val name: String)
    val a = User("Alice")
    val b = a.copy()
    println(a === b) // 输出 false

    //浅拷贝 复用同一个对象
    data class Book(val title: String)
    data class User(val name: String, val book: Book)

    val u1 = User("Bob", Book("Kotlin"))
    val u2 = u1.copy(name = "Alice")
    u2.book.title = "Java" // 会同时修改u1.book

  • 解构声明

    // 普通类
    class Student1(var name: String , var age: Int, var sex: Char) {

    复制代码
      // 注意事项:component0 顺序必须是 component1 component2 component3 和成员一一对应,顺序下来的
      operator fun component1() = name
      operator fun component2() = age
      operator fun component3() = sex

    }

    // 数据类
    data class Student2Data(var name: String , var age: Int, var sex: Char)

    fun main() {
    val(name, age, sex) = Student1("李四", 89, '男')
    println("普通类 结构后:name:name, age:age, sex:$sex")

    复制代码
      val(name1, age1, sex1) = Student2Data("李四", 89, '男')
      println("数据类 结构后:name:$name1, age:$age1, sex:$sex1")
    
      val(_, age2, _) = Student1("李四", 89, '男')
      println("数据类 结构后: age2:$age2")

    }

  • 运算符重载

    // 写一个数据类,就是为了,toString 打印方便而已哦
    data class AddClass2(var number1: Int, var number2: Int) {
    operator fun plus(p1: AddClass2) : Int {
    return (number1 + p1.number1) + (number2 + p1.number2)
    }
    }

    // TODO 94-Kotlin语言的运算符重载学习
    fun main() {
    // C++语言 +运算符重载就行了 -运算符重载就行了
    // KT语言 plus代表+运算符重载

    复制代码
      println(AddClass2(1, 1) + AddClass2(2, 2))

    }

  • 密封类
    ‌1. 替代枚举(Enum),但支持更灵活的数据类型‌
    ‌枚举的局限性‌:每个枚举值只能是单例,不能携带不同的数据。
    ‌密封类的优势‌:每个子类可以有自己的属性和方法,且可以是object(单例)或data class(带数据)。

    sealed class PaymentMethod {
    data class CreditCard(val cardNumber: String, val expiryDate: String) : PaymentMethod()
    data class PayPal(val email: String) : PaymentMethod()
    object Cash : PaymentMethod()
    }

‌2. 结合 when 表达式,实现编译期安全检查‌

复制代码
sealed class ApiResult {
    data class Success(val data: String) : ApiResult()
    data class Error(val message: String, val code: Int) : ApiResult()
}

fun handleResult(result: ApiResult) = when (result) {
    is ApiResult.Success -> println("成功: ${result.data}")
    is ApiResult.Error -> println("错误: ${result.message} (${result.code})")
    // 不需要 else,编译器确保所有情况已覆盖
}
  1. 适用于状态管理(如 UI 状态、业务逻辑状态)‌

    sealed class UiState {
    object Loading : UiState()
    data class Success(val data: List<String>) : UiState()
    data class Error(val message: String) : UiState()
    }

    fun updateUI(state: UiState) = when (state) {
    is UiState.Loading -> showProgressBar()
    is UiState.Success -> showData(state.data)
    is UiState.Error -> showError(state.message)
    }

‌4. 替代 when + else 的防御性编程‌

相关推荐
阿巴斯甜19 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker20 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952721 小时前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android