Kotlin標(biāo)準(zhǔn)庫(kù)函數(shù)
定義一個(gè)類(lèi)很簡(jiǎn)單,和java一樣聲明需要的變量屬性,在kotlin中省略了get()和set()函數(shù)默認(rèn)支持get()和set(),并且可以自定義get()和set()函數(shù);初始化類(lèi)時(shí)順序很重要,如果代碼順序?qū)戝e(cuò)了會(huì)很容易報(bào)錯(cuò);類(lèi)通過(guò)open修飾可被繼承,和java不同的是kotlin的函數(shù)也需要通過(guò)open修飾后子類(lèi)才可以繼承。

其它Kotlin文章
Android學(xué)習(xí)Kotlin之一、常量-條件-函數(shù)-高階函數(shù)
Android學(xué)習(xí)Kotlin之二、Null安全 -字符串操作- 類(lèi)型轉(zhuǎn)換
Android學(xué)習(xí)Kotlin之三、標(biāo)準(zhǔn)庫(kù)函數(shù)-集合List-Set-Map
Android學(xué)習(xí)Kotlin之四、定義類(lèi)-初始化-繼承
Android學(xué)習(xí)Kotlin之五、對(duì)象-接口-抽象類(lèi)
Android學(xué)習(xí)Kotlin之六、泛型-擴(kuò)展函數(shù)
本編文章會(huì)講到的知識(shí)點(diǎn)
- 定義類(lèi)
- field
- 計(jì)算屬性
- 初始化類(lèi)
- 主構(gòu)造函數(shù)使用臨時(shí)變量
- 主構(gòu)造函數(shù)中直接定義屬性變量
- 次構(gòu)造函數(shù)
- 初始化塊
- 初始化順序
- 延遲初始化lateinit
- 惰性初始化lazy
- 繼承
- open繼承
- 類(lèi)型檢測(cè)
- as智能轉(zhuǎn)換
- Any類(lèi)
定義類(lèi)
field
針對(duì)你定義的每一個(gè)屬性,Kotlin都會(huì)產(chǎn)生-個(gè)field、一個(gè)getter、 以及一個(gè)setter, field用來(lái)存儲(chǔ)屬性數(shù)據(jù),你不能直接定義field, Kotlin會(huì)封裝 field,保護(hù)它里面的數(shù)據(jù),只暴露給getter和setter使用。屬性的getter方法決定你如何讀取屬性值,每個(gè)屬性都有g(shù)etter方法,setter方 法決定你如何給屬性賦值,所以只有可變屬性才會(huì)有setter方法,盡管Kotlin會(huì)自動(dòng)提供默認(rèn)的getter和setter方法,但在需要控制如何讀寫(xiě)屬性數(shù)據(jù)時(shí),你也可以自定義他們。
- 定義一個(gè)Student類(lèi),里面定義變量,kotlin默認(rèn)提供的就有g(shù)et、set方法,也可以自定義get、set方法。
class Student {
var name = "小明"
get() = field.capitalize()
set(value) {
field = value.trim()//自定義set去除空格
}
var age = -12
//自定義get和set函數(shù),實(shí)際根據(jù)自己需求來(lái)自定義get和set
get() = field.absoluteValue//自定義取絕對(duì)值
set(value) {
field = value.absoluteValue
}
var adder:String? = "杭州"
}
- 創(chuàng)建Student對(duì)象,調(diào)用屬性的get、set方法使用
var student = Student()
student.name = " 老王 "http://估計(jì)前后寫(xiě)空格
println(student.name)//打印老王 沒(méi)有空格
println(student.age)
student.age = -6
println(student.age)//打印 是正6 因?yàn)樽远xget中取絕對(duì)值了
fun getAdder(){
//如果adder不為空才會(huì)打印
student?.adder?.also {
println("地址=${it}")
}
}
getAdder()
計(jì)算屬性
計(jì)算屬性是通過(guò)- -個(gè)覆蓋的get或set運(yùn)算符來(lái)定義,這時(shí)field就不需要 了。
var value: Int? = null
get() = (1..10).random()//自定義返回值get不使用field
var student = Student()
println(student.value)//返回1-10的隨機(jī)數(shù)
初始化類(lèi)
主構(gòu)造函數(shù)使用臨時(shí)變量
我們?cè)赥eacher類(lèi)的定義頭中定義一個(gè)主構(gòu)造函數(shù),使用臨時(shí)變量為T(mén)eacher的各個(gè)屬性提供初始值,在Kotlin中, 為便于識(shí)別,臨時(shí)變量(包括僅引用一-次的參數(shù)),通常都會(huì)以下劃線(xiàn)開(kāi)頭的名字命名。
class Teacher(
_name: String,
_age: Int,
) {
var name = _name
var age = _age
override fun toString(): String {
return "Teacher(name='$name', age=$age)"
}
}
var teacher = Teacher("何炅", 50)
println(teacher.name)//何炅
println(teacher.toString())//Teacher(name='何炅', age=50)

主構(gòu)造函數(shù)中直接定義屬性變量
Kotlin允許你不使用臨時(shí)變量賦值,而是直接用一個(gè)定義同時(shí)指定參數(shù)和類(lèi)屬性,通常,我們更喜歡用這種方式定義類(lèi)屬性,因?yàn)樗麜?huì)減少重復(fù)代碼。定義構(gòu)造函數(shù)時(shí),可以給構(gòu)造函數(shù)參數(shù)指定默認(rèn)值,如果用戶(hù)調(diào)用時(shí)不提供值參,就使用這個(gè)默認(rèn)值。
class Teacher2(
var name: String,
var age: Int = 10//可以設(shè)置默認(rèn)值
) {
override fun toString(): String {
return "Teacher2(name='$name', age=$age)"
}
}
var teacher2 = Teacher2("黃磊", 52)
println(teacher2.name)//黃磊
println(teacher2.toString())//Teacher2(name='黃磊', age=52)
次構(gòu)造函數(shù)
有主就有次,對(duì)應(yīng)主構(gòu)造函數(shù)的是次構(gòu)造函數(shù),我們可以定義多個(gè)次構(gòu)造函數(shù)來(lái)配置不同的參數(shù)組合,通過(guò)this指向把值傳遞給了主構(gòu)造函數(shù)??梢栽诖螛?gòu)造函數(shù)中進(jìn)行初始化代碼邏輯,比如修改參數(shù)值。
class Teacher3(
var name: String,
var age: Int,
) {
//次構(gòu)造函數(shù) 通過(guò)this指向把值傳遞給了主構(gòu)造函數(shù)
constructor(name:String):this(name,0){
//這里可以進(jìn)行初始化代碼邏輯,給age賦值
this.age = 18
}
override fun toString(): String {
return "Teacher3(name='$name', age=$age)"
}
}
val teacher3 = Teacher3("黃曉明")//調(diào)用的是次構(gòu)造函數(shù) 沒(méi)有傳age值
println(teacher3.toString())//Teacher3(name='黃曉明', age=18)
初始化塊
初始化塊可以設(shè)置變量或值,以及執(zhí)行有效性檢查, 如檢查傳給某構(gòu)造函數(shù)的值是否有效,初始化塊代碼會(huì)在構(gòu)造類(lèi)實(shí)例時(shí)執(zhí)行。
class Teacher4(
var name: String,
var age: Int,
) {
init {
println("${name} "+if (age>18) "滿(mǎn)18" else "未滿(mǎn)18")
age = if (age > 18) 1 else 0 //判斷age的值 然后修改age的值
}
override fun toString(): String {
return "Teacher4(name='$name', age=$age)"
}
}
var teacher4 = Teacher4("馬云",20)
println(teacher4.toString())//Teacher4(name='馬云', age=1)
初始化順序
1.主構(gòu)造函數(shù)里聲明的屬性
2.類(lèi)級(jí)別的屬性賦值
3.init初始化塊里的屬性賦值和函數(shù)調(diào)用
4.次構(gòu)造函數(shù)里的屬性賦值和函數(shù)調(diào)用
class Teacher5(
var name: String,
var age: Int,
) {
var hight: Int = 175
init {
println("初始化塊 ${name} " + if (age > 18) "滿(mǎn)18" else "未滿(mǎn)18")
}
constructor(name: String) : this(name, 10) {
hight = 180
println("這里是次構(gòu)造函數(shù)")
}
override fun toString(): String {
return "Teacher5(name='$name', age=$age, hight=$hight)"
}
}
var teacher5 = Teacher5("小馬云")
println(teacher5.toString())

延遲初始化lateinit
- 只能用在var變量上;
- 使用lateinit關(guān)鍵字相當(dāng)于做了一一個(gè)約定:在用它之前負(fù)責(zé)初始化;
- 只要無(wú)法確認(rèn)lateinit變量是否完成初始化,可以執(zhí)行isInitialized檢查;
只能用在var變量上;該修飾只能用于類(lèi)體中(不是在主構(gòu)造函數(shù)中)聲明的var屬性,注意是var(可變屬性)并且僅當(dāng)該屬性沒(méi)有自定義getter或setter時(shí),該屬性必須是非空類(lèi)型,并且不能是原生類(lèi)型。
class Teacher6 {
lateinit var name: String
init {
name = "中國(guó)驚奇先生"
}
fun getName() {
if (::name.isInitialized) println(name) else println("name為空")
}
}
val teacher6 = Teacher6()
teacher6.getName()
惰性初始化lazy
- 只能用在val變量上
延遲初始化并不是推后初始化的唯一方式, 你也可以暫時(shí)不初始化某個(gè)變量,直到首次使用它,這個(gè)叫作惰性初始化。
class Teacher7 {
val name: String by lazy {
println("馬上賦值")
"鎮(zhèn)魂街"
}
fun getName(){
println(name)
}
}
val teacher7 = Teacher7()
//第一次調(diào)用打印 “馬上賦值” “鎮(zhèn)魂街”
teacher7.getName()
//第二次調(diào)用只打印值,不會(huì)執(zhí)行l(wèi)azy{}過(guò)程
teacher7.getName()
繼承
open繼承
默認(rèn)都是封閉的,要讓某個(gè)類(lèi)開(kāi)放繼承,必須使用open關(guān)鍵字修飾它。父類(lèi)的函數(shù)也要以open關(guān)鍵字修飾,子類(lèi)才能覆蓋它。
open class Animal(var name: String) {
//父類(lèi)的函數(shù)也要以open關(guān)鍵字修飾,子類(lèi)才能覆蓋它。
open fun getName() {
println("this is ${name} ")
}
}
class Cat : Animal("小狗") {
override fun getName() {
// super.getName()
println("this2 is ${name} ")
}
}
val cat = Cat()
println(cat.name)//小狗
cat.getName()//this2 is 小狗
類(lèi)型檢測(cè)
Kotlin的is運(yùn)算符是個(gè)不錯(cuò)的工具,可以用來(lái)檢查某個(gè)對(duì)象的類(lèi)型。
val cat2 = Cat()
println(cat2 is Cat)//true
println(cat2 is Animal)//true
as智能轉(zhuǎn)換
as操作符聲明,這是一個(gè)類(lèi)型轉(zhuǎn)換。/為了避免拋出異常,可以使用安全轉(zhuǎn)換操作符 as?,它可以在失敗時(shí)返回 null。
println(cat2 as Animal)
var c = cat as Animal
// var c1 = cat2 as Animal2//報(bào)錯(cuò) java.lang.ClassCastException
var c1 = cat2 as? Animal2//為了避免拋出異常,可以使用安全轉(zhuǎn)換操作符 as?,它可以在失敗時(shí)返回 null
println(c1)
c?.getName()//this2 is 小狗
Any類(lèi)
無(wú)須在代碼里顯示指定,每一-個(gè)類(lèi)都會(huì)繼承一個(gè)共同的叫作Any的超類(lèi)。
val cat = Cat()
println(cat is Any)// true
println(cat as Any)// com.example.kotlinjetpack.kotlin.Cat@66d3c617