Kotlin核心编程

568 阅读7分钟
  • 打印类型名称
println(string.javaClass.name)
  • 如果kotlin没有声明返回值类型,则默认返回值类型为Unit
  • 声明类的属性
inner class Book(var name: String) {
        fun printName() {
            println(this.name)
        }
    }
  • 优先使用val写出防御性代码
  • 函数类型
(int) -> Unit
() -> Unit
(Int, String) -> Unit
(errorCode: Int, errMsg: String) -> Unit
(errorCode: Int, errMsg: String?) -> Unit
((errorCode: Int, errMsg: String?) -> Unit)?

/**
     * 函数类型参数
     */
    fun filter(name:String, filter: (country: Country) -> Unit) {
        
    } 
    
  • 返回值为一个函数
(Int) -> ((Int) -> Unit)
  • 双冒号调用类方法 class::fun
  • 匿名函数
  • 每个Function都有一个Invoke函数,所以想要执行函数体,需要调用函数.invoke()
private fun foo(int: Int) = { _: Int ->
        println(int.toString() + "fage")
    }

    private fun list() {
        listOf(1, 2, 3).forEach { foo(it).invoke(it) }
    }
  • Lambda
    • val sum: (Int, Int) -> Int = {x,y -> x+y}
    • 如果Lamba表达式的返回值不是Unit, 那么默认最后一行就是其返回值
  • 扩展函数
package com.example.kotlincore

import android.view.View

fun View.invisiable() {
    visibility = View.INVISIBLE
}

fun View.gone() {
    visibility = View.GONE
}
  • if else 保证代码安全,消除副作用
fun ifExpression(flag: Boolean) {
        val a = if (flag) "fage" else ""
    }
  • 枚举配合when表达式
package com.example.kotlincore

/**
 * 星期几枚举
 */
enum class Day(value: Int) {
    MON(1),
    TUE(2),
    WEN(3),
    THU(4),
    FRI(5),
    SAT(6),
    SUN(7)
}

/**
     * 日程
     */
    fun schedule(sunny: Boolean, day: Day) {
        when(day) {
            Day.SAT -> basketball()
            Day.SUN -> finish()
            Day.FRI -> appointment()
            else -> when {
                sunny -> library()
                else -> study()
            }
        }
    }

    fun basketball() {}
    fun fishing() {}
    fun appointment() {}
    fun library() {}
    fun study() {}

泛型

泛型类实现查找一个元素是否在数组中,是则返回本身,反之返回null

package com.example.kotlincore

/**
 * 查找数组中是否含有一个对象
 */
class SmartClass<T> : ArrayList<T>() {
    fun find(t: T) : T? {
        val index = super.indexOf(t)
        return if (index >= 0) super.get(index) else null
    }
}

使用扩展函数实现上面的需求

fun <T> ArrayList<T>.find(t: T): T? {
    val index = this.indexOf(t)
    return if (index >= 0) this[index] else null
}

Java泛型兼容

  • 因为泛型实Java1.5版本才引入的,所以Java允许没有具体类型参数的泛型类

类型约束上界

/**
 * 泛型类
 */
class Plate<T>(val t: T)    // 泛型类
open class Fruit(val weight: Double)    // 开放类
class Apple(weight: Double): Fruit(weight)  // 继承
class Banana(weight: Double): Fruit(weight) // 继承
class FruitPlate<T: Fruit>(val t: T)    // 泛型上界    

泛型擦除

  • Kotlin和Java中泛型是通过类型擦除来实现的,为什么呢
  • Java向后兼容:就是老版本的Java文件编译之后可以运行在新版本的JVM上

使用内联函数获取泛型

/**
 * 使用内联函数获取泛型类型
 */
inline fun <reified T : Any> Gson.fromJson(json: String) : T {
    return Gson().fromJson(json, T::class.java)
} 

协变

  • 只能读 out关键字 相当于传入的类型之能是约定类型的子类
/**
 * 协变
 */
interface ListCustom<out E> : Collection<E> {}

逆变

  • 与协变相反,相当于传入的类型是父类,只能写,不能读
interface ListCustom<in E> : Collection<E> {}

伴生对象的静态扩展函数

object Test {

    @JvmStatic
    fun main(args: Array<String>) {
        Log.d("tag", "fage")
    }
}

标准库中的扩展函数 run let also apply takeIf

run

  • 单独作用域
  • 重新定义变量
  • 返回范围内的最后一个对象

let apply

  • 类似,唯一不同的是返回值
  • apply返回的是原来的对象,let返回的是闭包的值,也就是闭包的最后一行

also

  • 与apply一致,返回的是原来的对象
  • 返回值是函数的接收者

takeIf

  • 不仅仅想判空,还想加入条件,这个时候let就显得有点不足了,就要使用takeIf了 val result = student.takeIf{it.age > 18}.let{...}

Android 中的扩展应用

  • 给ImageView添加扩展
fun ImageView.loadImage(url: String) {
    GlideApp.with(this.context)
            .load(url)
            .placeholder(R.mipmap.xxx)
            .error(R.mipmap.xxx)
            .into(this)
}

元编程

利用反射实现data class转换为Map

object Mapper {
    
    fun <A : Any> toMap(a : A): Map<String, Any?> {
        return a::class.members.map { m -> 
            val p = m as KProperty
            p.name to p.call(a)
        }.toMap()
    }
}

设计模式

抽象工厂模式: 为创建一组相关或者相互依赖的对象提供一个接口,而且无须指定他们的具体类

package com.example.kotlincore

import java.lang.IllegalArgumentException

interface Computer
class Dell: Computer
class Asus: Computer
class Acer: Computer
class DellFactory: AbstractFactory() {
    override fun produce(): Computer {
        return Dell()
    }
}

class AsusFactory: AbstractFactory() {
    override fun produce(): Computer {
        return Asus()
    }
}

class AcerFactory: AbstractFactory() {
    override fun produce(): Computer {
        return Acer()
    }
}

abstract class AbstractFactory {
    abstract fun produce(): Computer
    
    companion object {
        inline operator fun <reified T : Computer> invoke() : AbstractFactory {
            return when (T::class) {
                Dell::class -> {
                    DellFactory()
                }
                Asus::class -> {
                    AsusFactory()
                }
                Acer::class -> {
                    AcerFactory()
                }
                else -> {
                    throw IllegalArgumentException()
                }
            }
        }
    }
}

fun main(args: Array<String>) {
    val dellFactory = AbstractFactory<Dell>()
    val dell = dellFactory.produce()
}

构建者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

  • 解决构造函数一大堆的问题
  • 按需构造
  • 解决参数一大堆的时候的问题
package com.example.kotlincore

class Robot private constructor(
        val code: String,
        val battery: String?,
        val height: Int?,
        val weight: Int?
) {
    class Builder(private val code: String) {
        private var battery: String? = null
        private var height: Int? = null
        private var weight: Int? = null
        
        fun setBattery(battery: String?): Builder {
            this.battery = battery
            return this
        }
        
        fun setHeight(height: Int?): Builder {
            this.height = height
            return this
        }
        
        fun setWeight(weight: Int?): Builder {
            this.weight = weight
            return this
        }
        
        fun build(): Robot {
            return Robot(code, battery, height, weight)
        }
    }
}

fun main(args: Array<String>) {
    val robot = Robot.Builder("007")
            .setBattery("R6")
            .setHeight(300)
            .setWeight(200)
            .build()
}
  • 以上写法其实在Kotlin中已经可以简化,我们通过设置默认值的方式就可以
class Robot1 (
        val code: String,
        val battery: String? = null,
        val height: Int? = null,
        val weight: Int? = null
)

fun main(args: Array<String>) {
    val robot1 = Robot1("007")
    val robot2 = Robot1("004", height = 300)
    val robot3 = Robot1("008", height = 300, weight = 200)
}
  • 使用require关键字,对必要属性进行业务约束,使我们的业务更加安全
package com.example.kotlincore

class Robot1 (
        val code: String,
        val battery: String? = null,
        val height: Int? = null,
        val weight: Int? = null
) {
    init {
        require(weight == null || battery == null) {
            "Battery should be determined when setting weight."
        }
    }
}

fun main(args: Array<String>) {
    val robot1 = Robot1("007")
    val robot2 = Robot1("004", height = 300)
    val robot3 = Robot1("008", height = 300, weight = 200)
}

总结:在kotlin中,我们应该尽量避免使用构建者模式,因为kotlin支持具名的可选参数

行为型模式

Kotlin中的观察者模式

import java.util.*

/**
 * 被观察者
 */
class StockUpdate: Observable() {

    val observers = mutableSetOf<Observer>()

    fun setStockChanged(price: Int) {
        this.observers.forEach {
            it.update(this, price)
        }
    }
}

/**
 * 观察者
 */
class StockDisplay: Observer {
    override fun update(p0: Observable?, p1: Any?) {
        if (p0 is StockUpdate) {
            println("The latest stock price is $p1.")
        }
    }
}

/**
     * 使用
     */
    fun observer() {
        val su = StockUpdate()
        val sd = StockDisplay()
        su.observers.add(sd)
        su.setStockChanged(100)
    }
  • 通过上述的方式,简单实现了观察者模式

Kotlin中的可被观察的委托属性

  • 主要和上面的区别就是让需求更加具体,我们可以通过接口实现,来处理一大堆需要监听的逻辑
  • 首先写一个接口实现类
import kotlin.properties.Delegates

interface StockUpdateListener {
    fun onRise(price: Int)
    fun onFall(price: Int)
}
  • 然后在A Activity监听
class MainActivity : AppCompatActivity(), StockUpdateListener {
  • 然后在B Activity中实现调用
package com.example.kotlincore

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class SecondActivity: AppCompatActivity() {

    companion object {
        fun startActivity(context: Context) {
            val intent = Intent(context, SecondActivity::class.java)
            context.startActivity(intent)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        delegateObservable()
    }

    /**
     * 可被观察的委托模式
     */
    private fun delegateObservable() {
        val su = StockUpdate1()
        val sd = MainActivity()
        su.listeners.add(sd)
        su.price = 100
        su.price = 98
    }
}

策略模式

使用接口实现策略模式,以便于逻辑解耦

package com.example.kotlincore

interface SwimStrategy {
    fun swim()
}

class BreastStroke: SwimStrategy {
    override fun swim() {
        println("I am breaststroking...")
    }
}

class Backstroke: SwimStrategy {
    override fun swim() {
        println("I am backstroke")
    }
}

class Swimmer(val strategy: SwimStrategy) {
    fun swim() {
        strategy.swim()
    }
}

fun main() {
    val b1 = Swimmer(Backstroke())
    b1.swim()
    val b2 = Swimmer(BreastStroke())
    b2.swim()
}

使用高阶函数,使得策略模式更加简单,直接传入函数实现即可,而不必使用接口

package com.example.kotlincore

fun breaststroke() {
    println("I am breaststroking...")
}
fun backstroke() {
    println("I am backstroking...")
}
fun freestyle() {
    println("I am freestroking...")
}

class Swimmer1(val swimming: () -> Unit) {
    fun swim() {
        swimming()
    }
}

fun main() {
    val b1 = Swimmer1(::freestyle)
    b1.swim()
    val b2 = Swimmer1(::backstroke)
    b2.swim()
    val b3 = Swimmer1(::breaststroke)
    b3.swim()
}

模板方法模式,使用高阶函数来代替继承

  • 通常我们实现业务很多都使用了继承模式或者抽象类继承模式来实现模板代码
  • 例子:去市民中心办事,三个步骤
  • 1:取号排队
  • 2:办理具体业务
  • 3:评价
  • 先来写个抽象类,13实现,2由具体类实现
/**
 * 抽象类 去市民中心办事
 * 1:取号排队
 * 2:办理具体业务
 * 3:评价
 */
abstract class CivicCenterTask {
    fun execute() {
        this.lineUp()
        this.askForHelp()
        this.evaluate()
    }
    
    private fun lineUp() {
        println("排队")
    }
    private fun evaluate() {
        println("评价")
    }
    abstract fun askForHelp()
}
  • 实现
class PullSocialSecurity: CivicCenterTask() {
    override fun askForHelp() {
        println("拉取社保清单")
    }
}

class ApplyForCitizenCard: CivicCenterTask() {
    override fun askForHelp() {
        println("申请市民卡")
    }
}
  • 使用
private fun abstract() {
        val pass = PullSocialSecurity()
        pass.execute()
    }

依赖高阶函数来代替上面的抽象继承

class CivicCenterTask2 {
    fun execute(askForHelp: () -> Unit) {
        this.lineUp()
        askForHelp()
        this.evaluate()
    }
    
    private fun lineUp() {
        println("排队")
    }
    private fun evaluate() {
        println("评价")
    }
}

fun pullSocialSecurity() {
    println("拉取社保清单")
}

fun applyForCitizenCard() {
    println("申请市民卡")
}
  • 使用
private fun highFun() {
        val pass = CivicCenterTask2()
        pass.execute(::pullSocialSecurity)
    }
  • 可见,使用高阶函数的效果,和使用抽象函数继承实现的结果是一样的,但是代码量少了很多。一个函数即可解决问题