Kotlin—面向對象(一)

在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才初始化
    }
}

注意點

  1. 不能使用val來聲明
  2. 不能爲空
  3. 不能初始化

錯誤示範

    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")
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章