類與面向?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"
}
從面向過程到面向?qū)ο?,再到設(shè)計模式,架構(gòu)設(shè)計,面向服務(wù),Sass、Pass和Iass等思想,各種軟
件理論思想五花八門,但萬變不離其宗:
你要解決一個什么樣的問題?
你的問題是哪個領(lǐng)域的?
你的模型(數(shù)據(jù)結(jié)構(gòu))是什么?
你的算法是什么?
你對這個世界的本質(zhì)認知是怎樣的?
你的業(yè)務(wù)領(lǐng)域的邏輯問題、流程是什么?
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其實是一樣的。