kotlin核心编程pdf下载_Kotlin核心编程

本文深入探讨Kotlin编程的关键概念,包括类型系统、类的属性定义、函数类型、防御性编程、Lambda表达式、扩展函数、泛型、枚举与when表达式以及设计模式的应用。通过实例解析,展示Kotlin如何实现函数调用、类型约束、泛型擦除、行为型模式等高级特性。
部署运行你感兴趣的模型镜像

打印类型名称

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 : ArrayList() {

fun find(t: T) : T? {

val index = super.indexOf(t)

return if (index >= 0) super.get(index) else null

}

}

复制代码

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

fun ArrayList.find(t: T): T? {

val index = this.indexOf(t)

return if (index >= 0) this[index] else null

}

复制代码

Java泛型兼容

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

类型约束上界

/**

* 泛型类

*/

class Plate(val t: T) // 泛型类

open class Fruit(val weight: Double) // 开放类

class Apple(weight: Double): Fruit(weight) // 继承

class Banana(weight: Double): Fruit(weight) // 继承

class FruitPlate(val t: T) // 泛型上界

复制代码

泛型擦除

Kotlin和Java中泛型是通过类型擦除来实现的,为什么呢

Java向后兼容:就是老版本的Java文件编译之后可以运行在新版本的JVM上

使用内联函数获取泛型

/**

* 使用内联函数获取泛型类型

*/

inline fun Gson.fromJson(json: String) : T {

return Gson().fromJson(json, T::class.java)

}

复制代码

协变

只能读 out关键字 相当于传入的类型之能是约定类型的子类

/**

* 协变

*/

interface ListCustom : Collection {}

复制代码

逆变

与协变相反,相当于传入的类型是父类,只能写,不能读

interface ListCustom : Collection{}

复制代码

伴生对象的静态扩展函数

object Test {

@JvmStatic

fun main(args: Array) {

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 toMap(a : A): Map {

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 invoke() : AbstractFactory {

return when (T::class){

Dell::class ->{

DellFactory()

}

Asus::class ->{

AsusFactory()

}

Acer::class ->{

AcerFactory()

}

else -> {

throw IllegalArgumentException()

}

}

}

}

}

fun main(args: Array) {

val dellFactory = AbstractFactory()

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) {

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) {

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) {

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()

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)

}

复制代码

可见,使用高阶函数的效果,和使用抽象函数继承实现的结果是一样的,但是代码量少了很多。一个函数即可解决问题

您可能感兴趣的与本文相关的镜像

PyTorch 2.6

PyTorch 2.6

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值