-
繼承與重載的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 = _bodyInfofun 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() = nameoperator fun component2() = ageoperator 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,編譯器確保所有情況已覆蓋
}
- 適用于狀態管理(如 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 的防御性編程?