《Kotlin入門實戰(zhàn)》CH4 | 類與面向?qū)ο缶幊?/h2>

類與面向?qū)ο缶幊?/h1>

從面向過程到面向?qū)ο?,再到設(shè)計模式,架構(gòu)設(shè)計,面向服務(wù),Sass、Pass和Iass等思想,各種軟
件理論思想五花八門,但萬變不離其宗:

你要解決一個什么樣的問題?
你的問題是哪個領(lǐng)域的?
你的模型(數(shù)據(jù)結(jié)構(gòu))是什么?
你的算法是什么?
你對這個世界的本質(zhì)認知是怎樣的?
你的業(yè)務(wù)領(lǐng)域的邏輯問題、流程是什么?

聲明類

1. 空類

2. 聲明類和構(gòu)造函數(shù)

class People(var id: Int) {
    var age: Int = 0;           // 沒有延遲初始化的必須聲明的時候初始化
    lateinit var name: String;  // 延遲初始化

    // 二級構(gòu)造器必須調(diào)用主構(gòu)造器
    // 構(gòu)造器中參數(shù)不能使用val或者var聲明
    constructor(id: Int, age: Int, name: String) : this(id) {
        this.age = age
        this.name = name
    }

    // 重寫toString方法
    override fun toString(): String {
        return "People(id=$id, age=$age, name='$name')"
    }
}


fun main() {
    val people = People(42119999)   // 調(diào)用主構(gòu)造器
    people.age = 20                 // 類中屬性默認是public,在其他包中也可以訪問
    people.name = "kris"
}

當子類繼承了某個類之后,便可以使用父類中的成員變量,但并不是完全繼承父類的所有成員變量。具體的原則如下:

  • 能夠繼承父類的public和protected成員變量;
  • 不能繼承父類的private成員變量;
  • 對于父類的包訪問權(quán)限成員變量,如果子類和父類在同一個包下,則子類能夠繼承;否則,子類不能繼承;
  • 對于子類可以繼承的父類成員變量,如果在子類中出現(xiàn)了同名稱的成員變量,則會發(fā)生隱藏現(xiàn)象,即子類的成員變量會屏蔽掉父類的同名成員變量。如果要在子類中訪問父類中的同名成員變量,需要使用super關(guān)鍵字進行引用。

3 Object對象

Kotlin中沒有靜態(tài)對象,需要實現(xiàn)單例模式,可以使用Object單例對象

object User{
    var id = "admin"
    var pw = "admin"

    override fun toString(): String {
        return "$id + $pw"
    }
}

fun main() {
    println(User) //  admin + admin
}

或者使用伴生對象

class DBClient(var id : Int){
    fun open(){
        println("DBClient id $id")
        openDB()
    }

    // 伴生對象,一個類只有一個
    companion object DBEngine{
        fun openDB(){
            println("DB engine open db")
        }
    }
}

fun main() {
    DBClient(1).open()
    DBClient(2).open()
}
/*
DBClient id 1
DB engine open db
DBClient id 2
DB engine open db
*/

4. 數(shù)據(jù)類

//主構(gòu)造器不能為空
data class Music(var id : Int){
    lateinit var name : String;
}

這是Kotlin的數(shù)據(jù)類,可以反編譯一下,查看對應(yīng)的Java代碼

public final class Music {
   @NotNull
   public String name; // 在類中聲明的變量是public的
   private int id; // 主構(gòu)造器中變量式私有的,也就是說不能繼承
   
   // 構(gòu)造器 
   public Music(int id) {
      this.id = id;
   }
    
// ============= get and set fun
   // get&set 都是被聲明為final,不能重寫
   @NotNull
   public final String getName() {
      String var10000 = this.name;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("name");
      }

      return var10000;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name = var1;
   }
    
   public final int getId() {
      return this.id;
   }

   public final void setId(int var1) {
      this.id = var1;
   }
//===============

   // component1 返回主構(gòu)造器中下表為1的屬性值
   public final int component1() {
      return this.id;
   }
   
   // 拷貝函數(shù)
   @NotNull
   public final Music copy(int id) {
      return new Music(id);
   }

   // $FF: synthetic method
   @NotNull
   public static Music copy$default(Music var0, int var1, int var2, Object var3) {
      if ((var2 & 1) != 0) {
         var1 = var0.id;
      }

      return var0.copy(var1);
   }
   // 只包含主構(gòu)造器中的域
   @NotNull
   public String toString() {
      return "Music(id=" + this.id + ")";
   }
   // 只包含主構(gòu)造器中的域
   public int hashCode() {
      return this.id;
   }
   // 只包含主構(gòu)造器中的域
   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof Music) {
            Music var2 = (Music)var1;
            if (this.id == var2.id) {
               return true;
            }
         }

         return false;
      } else {
         return true;
      }
   }
}

  • 主構(gòu)造函數(shù)至少包含一個參數(shù);
  • 參數(shù)必須標識為val或者var;
  • 不能為abstract、open、sealed或者inner;
  • 不能繼承其他類(但可以實現(xiàn)接口)。
  • 可以在解構(gòu)聲明中使用

Pair

Kotlin中提供了二元組Pair,和三元組Triple,可以使用Pair實現(xiàn)Map

public data class Pair<out A, out B>(
    public val first: A,
    public val second: B
) : Serializable {
    public override fun toString(): String = "($first, $second)"
}

/**
 * Creates a tuple of type [Pair] from this and [that].
 *
 * This can be useful for creating [Map] literals with less noise, for example:
 * @sample samples.collections.Maps.Instantiation.mapFromPairs
 */
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
// 重寫了中綴表達式to

使用Pair實現(xiàn)Map

fun main() {
    val map = mapOf(1 to 'A', 2 to 'B', 3 to 'C')
    println(map) // 創(chuàng)建的是LinkedHashMap類型的Map
}

// mapOf方法在 kotlin.collections包中(默認導(dǎo)入)
public fun <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V> =
    if (pairs.size > 0) pairs.toMap(LinkedHashMap(mapCapacity(pairs.size))) else emptyMap()

內(nèi)部類

1.普通內(nèi)部類

一個類可以嵌套其他類中,并且可以嵌套多層,普通內(nèi)部類不持有外部類的引用,所以不能訪問外部類屬性。

class Out{
    var v = 1
    class inner{
        fun cout(){
            println(v) // Error
        }
    }
}

2.嵌套內(nèi)部類

如果需要在內(nèi)部類中獲取外部類的this指針,可以使用嵌套內(nèi)部類

class Out{
    var v = 1

    inner class inner{
        fun cout(){
            println(v) // OK
        }
    }
}

3.匿名內(nèi)部類

匿名內(nèi)部類也可以訪問外部類屬性。匿名內(nèi)部類最經(jīng)典的運用場景應(yīng)該就是創(chuàng)建子線程

class MyThread {
    // 匿名內(nèi)部類實現(xiàn)
    fun doRun1() {
        Thread(object : Runnable {
            override fun run() {
                println(Thread.currentThread().id)
            }
        }).start()
    }

    // Lambda表達式實現(xiàn)
    fun doRun2() {
        Thread(Runnable {
            println(Thread.currentThread().id)
        }).start()
    }

    //使用lambda表達式和匿名內(nèi)部類
    fun doRun3() {
        val run = Runnable {
            println(Thread.currentThread().id)
        }
        Thread(run).start()
    }

    // 直接使用lambda表達式
    fun doRun4() {
        val run = {
            println(Thread.currentThread().id)
        }
        Thread(run).start()
    }

}


fun main() {
    println(Thread.currentThread().id)  // 1
    MyThread().doRun1()                 // 12
    MyThread().doRun2()                 // 13
    MyThread().doRun3()                 // 14
    MyThread().doRun4()                 // 15
}

方法4和方法2其實是一樣的。方法1和方法3其實是一樣的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 面向?qū)ο缶幊蹋∣OP) 在前面的章節(jié)中,我們學習了Kotlin的語言基礎(chǔ)知識、類型系統(tǒng)、集合類以及泛型相關(guān)的知識。...
    Tenderness4閱讀 4,607評論 1 6
  • 原文鏈接:https://github.com/EasyKotlin 在前面的章節(jié)中,我們學習了Kotlin的語言...
    JackChen1024閱讀 922評論 0 3
  • Kotlin的類和接口與Java的類和接口是有一定的區(qū)別的。Kotlin的接口是可以包含屬性聲明。Kotlin默認...
    程自舟閱讀 10,520評論 0 11
  • 寫在開頭:本人打算開始寫一個Kotlin系列的教程,一是使自己記憶和理解的更加深刻,二是可以分享給同樣想學習Kot...
    胡奚冰閱讀 1,517評論 5 11
  • 成長是每個人都會經(jīng)歷的事情,從出生到老去,成長更多的是年齡遞增的一個統(tǒng)稱解釋。 長大無關(guān)于年齡,更多的是責任、擔當...
    蹲在陰暗處的人閱讀 153評論 0 0

友情鏈接更多精彩內(nèi)容