Kotlin筆記

Class與KClass

擴展函數

基本使用

定義一個Person類java

class Person{

}
複製代碼

在Expand.kt文件定義Person類擴展函數bash

fun Person.name(name: String) {
    println(name)
}

fun Person.age(age: String) = println(age)
複製代碼

kotlin使用擴展函數ide

val person = Person()
person.name("zhang")
person.age("97")

複製代碼

java使用擴展函數函數

Person person = new Person();
ExpandKt.name(person,"zhang");
ExpandKt.age(person,"97");

複製代碼

擴展函數的靜態解析

擴展函數支持多態嗎?佈局

擴展函數是靜態添加的,不具備運行時的多態效應優化

open class Animal
class Dog : Animal()


fun Animal.name(): String = "animal"
fun Dog.name(): String = "dog"


fun Animal.printName(animal: Animal) {
    println(animal.name())
}

fun main() {
    val dog = Dog()
    dog.printName(dog)
}


複製代碼

轉爲java,會強轉爲Animal,因此不支持多態ui

public static final void main() {
      Dog dog = new Dog();
      printName((Animal)dog, (Animal)dog);
   }

複製代碼

Lambda

// lambda寫法
var say = { name: String, age: Int ->
    println("my name is $name,and I am $age")
}
// 函數寫法
fun say1(name: String, age: Int): Unit {
    println("my name is $name,and I am $age")
}

fun main() {
    say("zhang", 97)
    say1("zhang", 97)
}
複製代碼

my name is zhang,and I am 97this

my name is zhang,and I am 97spa

最多22個參數

var sayMany = { p1: String, p2: String, p3: String,
                p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String,
                p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String, p20: String, p21: String,
                p22: String//若是這裏有p23:String,會報錯說沒有Function23
    ->
    println("my name is $p1")
}

sayMany("a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a","a")

複製代碼

my name is a3d

新版本kotlin解決了這個問題,個人的這個版本參數是能夠超越22的,緣由以下

var sayMany = { p1: String, p2: String, p3: String,
                p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String,
                p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String, p20: String, p21: String,
                p22: String, p23: String, p24: String
    ->
    println("my name is $p1")
}
複製代碼

轉爲java

static {
      say = (Function2)null.INSTANCE;//兩個參數的
      sayMany = (FunctionN)null.INSTANCE;//22參數以上的
   }
複製代碼

高階函數

// 高階函數,參數或者返回值,是一個函數(或者Lambda)

fun onlyif(isDebug: Boolean, block: () -> Unit) {
    if (isDebug) {
        block()
    }
}

fun main() {
    onlyif(true) { println("打印日誌") }
}
複製代碼

如何把函數做爲參數傳遞給另外一個函數:函數的引用

// 1. 定義一個runnable對象
val runnable = Runnable {
    println("Runnable::run 這是一個函數引用 ::")
}
// 2. 聲明一個函數叫作 function,這個函數類型是 ()->Unit
val function: () -> Unit
// 3. 如今要給function這個函數賦值,這個值必須也是一個函數,而且類型也是()->Unit
// function = runnable.run()//不能這樣寫,runnable.run()表示把執行結果賦值給了function
function = runnable::run//這就對了,把函數的引用賦值給function

onlyif(true, function)
複製代碼

Runnable::run 這是一個函數引用 ::

用內聯優化代碼 關鍵字:inline(相似於佈局裏的include)

白話kotlin:內聯函數助你提高運行效率

對比下面的代碼,區別只是在高階函數onlyif以前加了一個inline

inline fun onlyif(isDebug: Boolean, block: () -> Unit) {
    if (isDebug) {
        block()
    }
}

fun main() {
    onlyif(true) { println("打印日誌") }

}
複製代碼

fun onlyif1(isDebug: Boolean, block: () -> Unit) {
    if (isDebug) {
        block()
    }
}

fun main() {
    onlyif1(true) { println("打印日誌") }

}
複製代碼

可是不建議處處使用inline,通常只是在高級函數前面使用,用他的目的是爲了減小沒必要要的由Lambda表達式帶來的匿名對象 過分使用inline會給編譯器帶來負擔,查找問題變得複雜,不建議亂用這inline

構造函數

主構造函數

寫在類聲明的地方

open class Person(name: String)

class Man(name: String) : Person(name){
    init {
        println("構造函數執行時,我會執行的 $name")
    }
}

fun main() {
    Man("zhang")
}

複製代碼

次構造函數

若是由多個構造函數,第二個構造函數經過次構造函數實現,寫到類內部

次構造函數,必須直接或間接調用該類主構造函數,或者改類的父類構造函數

open class Person(name: String) 

class Man(name: String) : Person(name) {
    private var age: Int = 0
    private var address: String = ""

    init {
        println("構造函數執行時,我會執行的 $name")
    }

    constructor(name: String, age: Int) : this(name) {
        this.age = age
    }

    constructor(name: String, age: Int, address: String) : this(name,age) {
        this.address = address
    }

}

fun main() {
    Man("zhang")
    Man("zhang", 97)
    Man("zhang", 97, "beijng")
}
複製代碼

伴生對象

相似java靜態

class StringUtils{
    companion object{
        fun isEmpty(str: String): Boolean {
          return str.isEmpty()
        }
    }
}

fun main() {
    val empty = StringUtils.isEmpty("")
}
複製代碼

若是java裏想像靜態同樣使用這個伴生對象方法,要加上@Jvmstatic

class StringUtils {
    companion object {
        @JvmStatic
        fun isEmpty(str: String): Boolean {
            return str.isEmpty()
        }
}

複製代碼
public class JavaC {
    public static void main(String[] args) {
        StringUtils.isEmpty("str");
    }
}

複製代碼

使用伴生對象的單例模式寫法(推薦寫法)

固然直接使用object也行

class Single private constructor() {
    companion object {
        fun get(): Single {
            return Holder.instance
        }
    }

    private object Holder {
        val instance = Single()
    }
}
複製代碼

動態代理(by)

java 的寫法是很繁瑣的

interface Drive {
    fun driving()
}

class MiShu : Drive {
    override fun driving() {
        println("我是祕書,我在開車。。。")
    }
}

// Manager代理類,Mishu被代理類,他們都實現Drive接口
// 經理本身不用實現開車方法,,他是用的是祕書的開車方法
class Manager(drive: Drive) : Drive by drive {

}

fun main() {
    Manager(MiShu()).driving()
}
複製代碼

我是祕書,我在開車。。。

interface Drive {
    fun driving()
}

class MiShu : Drive {
    override fun driving() {
        println("我是祕書,我在開車。。。")
    }
}

// Manager代理類,Mishu被代理類,他們都實現Drive接口
//一旦經理本身實現了開車方法,那麼就是經歷本身開車了
class Manager(drive: Drive) : Drive by drive {
    override fun driving() {
        println("我是經理,我在開車。。。")
    }

}

fun main() {
    Manager(MiShu()).driving()
}


複製代碼

我是經理,我在開車。。。

相關文章
相關標籤/搜索