在Kotlin中有兩大思想,分別是面相對象編程和函數式編程,從今起進入我們就要攻克這兩大核心思想,先是面相對象的學習和使用。
一、面相對象三大特徵
先簡單介紹面相對象的知識,你現在只需要有一個抽象的認識。
說起面相對象就要說一下面向過程
面向過程:分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。
面向對象:把構成問題事務分解成各個對象,建立對象的目的不是爲了完成一個步驟,而是爲了描敘某個事物在整個解決問題的步驟中的行爲。
直觀點解釋比如:一個圍棋遊戲,面相過程就是設計開始遊戲畫面,然後初始化棋盤,判斷需要時間,然記錄等。
而面相對象,則是創建開始遊戲和棋盤、棋子、記錄等。
封裝
將某些信息隱藏在內部,不允許外部程序直接訪問,而是通過提供的函數來實現對隱藏信息的操作和訪問。
繼承
繼承就是獲取到父親的屬性和函數,可以在自己使用也可以更改或者重寫
多態
通常在搭建框架中使用。
二、面相對象基礎
1 類
從創建一個類開始,在一個類中可以有很多屬性和函數。Kotlin中的類Java的類比較類似。
new 一個Kotlin Class,取個名字就行。
class Demo {
}
這就是一個簡單的Class,是面對象中經常使用的基礎單位。
2 屬性
在Kotlin中聲明一個屬性很簡單,只需要 var或者val+屬性名稱+=值
val name="王"
當然你可以加上屬性類型,然後告訴可空類型,然後不給值
var name:String? = null
2.1.延遲屬性
延遲屬性在Java沒有的,一般我們都是先賦值null,再在需要的時候賦值。在Kotlin中就是使用關鍵字
lateinit var student: Student //引用數據類型
lateinit var s: String //基本數據類型
這樣的好處是在使用的時候纔開闢內存,進行初始化,節約內存。
下面的Demo類中聲明延遲屬性是並沒有初始化,二十在調用是才初始化再調用
class Demo {
lateinit var p: Person //聲明延遲屬性
fun test() {
println(p.name) //在這Person才初始化
}
}
注意點
- 不能使用val來聲明
- 不能爲空
- 不能初始化
錯誤示範
lateinit var student: Student = null //不能爲空
lateinit val s: String //不能爲val
lateinit var student2: Student = Student() //不能初始化
3擴展
在Kotlin中擁有一種機制叫擴展,它在類的外面直接擴展屬性和函數。
3.1擴展屬性
class Person() {
val name: String = "王"
}
var Person.id: String
get() = "Person的id爲1"
set(value) = println(value)
fun main(args: Array<String>) {
var person=Person()
println(person.id)
}
結果
3.2.擴展函數
class Person() {
val name: String="王"
}
fun Person.person(){
println("Person的擴展函數person")
}
fun main(args: Array<String>) {
var person=Person()
person.person()
}
2.3.成員屬性和擴展屬性優先級
成名屬性優先級比擴展屬性高,
class Person() {
val name: String = "王"
}
var Person.name: String
get() = "控制name"
set(value) {
println(value)
}
fun main(args: Array<String>) {
var person=Person()
println(person.name)
}
結果
3.綴運算符
什麼綴運算符,就是經常使用的+,-啊,都是。
infix fun Int.add(int: Int): Int {
return this + int
}
fun main(args: Array<String>) {
var a=1
println(a add 1)
}
結果:
4.構造函數
構造函數,分爲兩種,主構造函數,和次構造函數。主構造函數在類的名稱後面,次構造函數則在類裏。
4.1主構造函數
和Java相同每一個類都有默認的構造函數,既無參構造函數。
class Person() {
fun p() {
println("使用無參構造函數,創建對象")
}
}
fun main(args: Array<String>) {
var person = Person(); //這裏就是使用無慘構造函數創建對象
person.p()
}
結果:
有參構造函數
class Person(name: String) {
var name = name
}
fun main(args: Array<String>) {
var person = Person("王"); //使用有參構造函數
println(person.name)
}
結果:
完整寫法
class Person constructor(name: String) {
var name: String
init {
this.name = name
}
}
fun main(args: Array<String>) {
var person = Person("王");
println(person.name)
}
當然constructor可以省略掉,也要注意不能省略的情況。
靈活使用
public class Person(var name: String, var sex: Boolean = true) {
}
4.2次構造函數
當主構造函數,不夠靈活時,可以使用次構造函數,來方便使用。
fun main(args: Array<String>) {
var person = Person("wang"); //使用主構造函數
var person2 = Person("wang", false) //使用次構造函數
var person3 = Person("wang", false,1) //使用次構造函數
}
public class Person(name: String) {
var name: String
var sex = true
var age: Int = 0
init {
this.name = name
}
constructor(name: String, sex: Boolean) : this(name) {
this.sex = sex
}
constructor(name: String, sex: Boolean, age: Int) : this(name) {
this.sex = sex
this.age = age
}
}
5.可見性修飾符
1.共有的修飾符
public 是kotlion默認修飾符,它可以申明類、函數、屬性,也可以聲明頂層的函數和屬性,它屬於公共的。
2.保護修飾符
protected和Java的一樣,只有子類繼承後纔可以使用。
3.內部可見性修飾符
internal 是模塊可見,在同一個模塊和public,在不同的模塊和private相似。注意,模塊不是包和Java不同
4.私有修飾符
private 就是隻有自己纔可以訪問到。
6.Any類
Any類和java的Object類。所有Kotlin中的類都繼承了Any類。這個類裏有三個函數
equals:比較其它對象是否和這個對象相等
hashCode:返回改對象的哈希碼
toSting:返回該對象的字符串表示
7.數據類
使用data聲明的類叫數據類,它自動重寫Any中的三個函數和一個copy函數。
聲明一個data類
data class Person(var name: String,var sex:String,var age:Int) {
}
注意data類不能省略var或者val
copy函數使用
fun main(args: Array<String>) {
var p = Person("wang", "nan", 20)
var a = p.copy()
println(p)
println(a)
println(p==a)
}
此時a就和p一樣了
解構data類
解構和創建都是對對象操作的。創建一個對象使用構造函數,解構一個對象,就是被一個對象中屬性拿出來。
fun main(args: Array<String>) {
var p = Person("wang", "nan", 20)
val (name, sex) = p
println(name)
println(sex)
}
這裏的括號對應這構造函數的屬性的順序。
結果:
一般,你不會全部使用,對象裏的值,你可以這樣
fun main(args: Array<String>) {
var p = Person("wang", "nan", 20)
var (name) = p
var (name2, _) = p
println(name)
println(name2)
}
8.枚舉類
枚舉類是用來管理一堆常量的。
9.嵌套類
class Person() {
var name: String? = null
class Hand() {
fun hand() {
println("手")
println(name) //報錯
}
}
}
fun main(args: Array<String>) {
var person = Person()
val hand = Person.Hand()
}
嵌套類不能訪問外部類
10.內部類
內部類可以訪問外部類屬性和函數。
class Person() {
var name: String? = "人"
var age = 20
inner class Hand() {
var name: String = "手"
fun hand() {
println([email protected]) //訪問外部類屬性
println(this.name) //訪問內部類屬性
println(name) //訪問內部類屬性
println(age) //訪問外部類屬性
}
}
}
內部類創建是和嵌套類使用不同,它需要先創建外部類對象,再創建內部類對象。
fun main(args: Array<String>) {
var person = Person()
val hand = person.Hand()
hand.hand()
}
結果:
二、object關鍵字
聲明並且創建一個類,可以用於對象表達式、對象聲明和伴生對象
聲明匿名內部類
fun main(args: Array<String>) {
object : InterfaceDemo {
override fun demo() {
}
}
}
object代表一個類,然後實現了一個接口,重寫它抽象方法
也可以繼承一個類和實現接口
var person = object : Person(), InterfaceDemo {
override fun demo() {
}
}
也可以直接聲明一個類使用
var person = object {
var name: String = "wang"
}
聲明一個單例模式
object Person {
var name: String? = "人"
var age = 20
fun hand() {
println("hand")
}
}